I have strange behavior from the Kendo MVC grid (version R2 2021) when used in a Sitefinity Widget (Sitefinity version 13.3.7600). The grid appears to not bind properly to the datasource in any browser except Internet Explorer 11. I've tried Firefox (89.0), Chrome (91.0.4472.77) and Edge (91.0.864.41). For some reason Internet Explorer works.
Originally I was thinking it had to do with some of the Kendo .js scripts and/or .css files not being loaded before the bind operation, but as a test I added a refresh button and set AutoBind(false). The Controller, Model and View code work just fine in my standalone test application but when the same code is used in a Sitefinity Widget the data won't appear.
The Controller's action method is being called (I set a breakpoint) and returning what appears to be properly formatted JSON data. I have tried switching the grid to bind on a <dynamic> (instead of my specific class) and using the .Model() syntax, I have even tried different Models, including some without a List<> and just 6 separate decimal properties to see if it was a problem using a collection (it wasn't).
In each case all the test code I try **works in Internet Explorer** and not any other major browser.
*NOTE: My Widgets are all in their own separate assembly (which is why you'll see the ControllerToolboxItemAttribute). That .csproj is included in my Sitefinity solution.*
The following is an example of what I'm using:
**Model Classes (Mvc\Models)**
```
namespace MyWidget.Mvc.Models
{
public class MyRateClass
{
public string Maturity { get; set; }
public List<decimal> Rates { get; set; }
}
}
```
```
namespace MyWidget.Mvc.Models
{
public class MyRatesViewModel
{
public int MaxTiers { get; set; }
public string Message { get; set; }
}
}
```
**Controller (Mvc\Controllers)**
```
using MyWidget.Mvc.Models;
using System.Collections.Generic;
using System.Web.Mvc;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;
using Telerik.Sitefinity.Mvc;
namespace MyWidget.Mvc.Controllers
{
[ControllerToolboxItem(Name = "MyWidget.Mvc.Controllers.Rates", SectionName = "CustomWidgets", Title = "My Broken Widget")]
public class RatesController : Controller
{
public ActionResult Index()
{
MyRatesViewModel vm = new MyRatesViewModel() {
MaxTiers = 6, Message = "Broken"
};
return View(vm);
}
public ActionResult RetrieveRates([DataSourceRequest] DataSourceRequest request)
{
// Mock Data
List<MyRateClass> reportRates = new List<MyRateClass>()
{
new MyRateClass() { Maturity = "1", Rates = new List<decimal>() { 0, 0, 0, 0, 0, 0 } },
new MyRateClass() { Maturity = "2", Rates = new List<decimal>() { 0.07453M, 0.0623M, 0, 0, 0, 0 } }
};
DataSourceResult dsResult = reportRates.ToDataSourceResult(request);
return Json(dsResult, JsonRequestBehavior.AllowGet);
}
}
}
```
**View (Mvc\Views\Rates)** - Verison using .AutoBind(false)
*NOTE: The links that begin with "kendoui/" are all pointing to files in my Sitefinity/ResourcePackages directory. They do load properly. I have also tried them as embledded resources in my Widget assembly and they work that way as well.*
```
@using MyWidget;
@using MyWidget.Mvc.Models;
@using Kendo.Mvc.UI;
@using Kendo.Mvc.Extensions;
@using Telerik.Sitefinity.Frontend.Mvc.Helpers;
@using Telerik.Sitefinity.Modules.Pages;
@model MyRatesViewModel
@Html.StyleSheet(Url.WidgetContent("kendoui/styles/kendo.common.min.css"), "head", false)
@Html.StyleSheet(Url.WidgetContent("kendoui/styles/kendo.default.min.css"), "head", false)
@Html.StyleSheet(Url.WidgetContent("kendoui/styles/kendo.bootstrap-v4.min.css"), "head", false)
@Html.Script(ScriptRef.JQuery, "head") <!-- required for Kendo to work -->
@Html.Script(Url.WidgetContent("kendoui/js/jszip.min.js"), "head") <!-- required for Excel Exports to work -->
@Html.Script(Url.WidgetContent("kendoui/js/kendo.all.min.js"), "head") <!-- required for Kendo MVC to work -->
@Html.Script(Url.WidgetContent("kendoui/js/kendo.aspnetmvc.min.js"), "head") <!-- required for Kendo MVC to work -->
<div class="row">
<div class="col-12">
<div>
<table style="overflow: auto; border-collapse: collapse; width: 100%; max-width: 600px;">
<tr>
<td style="border-right: #aca899 1px solid; border-top: #aca899 1px solid; border-left: #aca899 1px solid;">
<p>@Model.Message</p>
</td>
</tr>
</table>
</div>
@(Html.Kendo().Grid<MyWidget.Mvc.Models.MyRateClass>()
.Name("rategrid")
.AutoBind(false)
.Columns(columns =>
{
columns.Bound(p => p.Maturity);
for (int i = 0; i < Model.MaxTiers; i++)
{
var tier = i + 1;
columns.Template(p => { }).ClientTemplate(string.Format("#=kendo.toString(Rates['{0}'], \"0.00\")#", i)).Title(string.Format("Tier {0}", tier));
}
})
.ToolBar(toolbar =>
{
toolbar.Excel();
})
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Multiple)
.Type(GridSelectionType.Row))
.AllowCopy(true)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.PageSize(25)
.Read(read => read.Action("RetrieveRates", "Rates"))
)
)
</div>
</div>
<input type="button" onclick="myfunction ()" value="Load Grid">
<script type = "text/javascript">
function myfunction() {
var grid = $("#rategrid").data("kendoGrid");
grid.dataSource.read();
grid.refresh();
}
```
Clicking "Load Grid" will properly refresh the empty grid and cause it to display 2 rows when used in IE 11. The fact that this works in IE 11 and not in any other is a real head scratcher. Any assistance is appreciated!
Originally I was thinking it had to do with some of the Kendo .js scripts and/or .css files not being loaded before the bind operation, but as a test I added a refresh button and set AutoBind(false). The Controller, Model and View code work just fine in my standalone test application but when the same code is used in a Sitefinity Widget the data won't appear.
The Controller's action method is being called (I set a breakpoint) and returning what appears to be properly formatted JSON data. I have tried switching the grid to bind on a <dynamic> (instead of my specific class) and using the .Model() syntax, I have even tried different Models, including some without a List<> and just 6 separate decimal properties to see if it was a problem using a collection (it wasn't).
In each case all the test code I try **works in Internet Explorer** and not any other major browser.
*NOTE: My Widgets are all in their own separate assembly (which is why you'll see the ControllerToolboxItemAttribute). That .csproj is included in my Sitefinity solution.*
The following is an example of what I'm using:
**Model Classes (Mvc\Models)**
```
namespace MyWidget.Mvc.Models
{
public class MyRateClass
{
public string Maturity { get; set; }
public List<decimal> Rates { get; set; }
}
}
```
```
namespace MyWidget.Mvc.Models
{
public class MyRatesViewModel
{
public int MaxTiers { get; set; }
public string Message { get; set; }
}
}
```
**Controller (Mvc\Controllers)**
```
using MyWidget.Mvc.Models;
using System.Collections.Generic;
using System.Web.Mvc;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;
using Telerik.Sitefinity.Mvc;
namespace MyWidget.Mvc.Controllers
{
[ControllerToolboxItem(Name = "MyWidget.Mvc.Controllers.Rates", SectionName = "CustomWidgets", Title = "My Broken Widget")]
public class RatesController : Controller
{
public ActionResult Index()
{
MyRatesViewModel vm = new MyRatesViewModel() {
MaxTiers = 6, Message = "Broken"
};
return View(vm);
}
public ActionResult RetrieveRates([DataSourceRequest] DataSourceRequest request)
{
// Mock Data
List<MyRateClass> reportRates = new List<MyRateClass>()
{
new MyRateClass() { Maturity = "1", Rates = new List<decimal>() { 0, 0, 0, 0, 0, 0 } },
new MyRateClass() { Maturity = "2", Rates = new List<decimal>() { 0.07453M, 0.0623M, 0, 0, 0, 0 } }
};
DataSourceResult dsResult = reportRates.ToDataSourceResult(request);
return Json(dsResult, JsonRequestBehavior.AllowGet);
}
}
}
```
**View (Mvc\Views\Rates)** - Verison using .AutoBind(false)
*NOTE: The links that begin with "kendoui/" are all pointing to files in my Sitefinity/ResourcePackages directory. They do load properly. I have also tried them as embledded resources in my Widget assembly and they work that way as well.*
```
@using MyWidget;
@using MyWidget.Mvc.Models;
@using Kendo.Mvc.UI;
@using Kendo.Mvc.Extensions;
@using Telerik.Sitefinity.Frontend.Mvc.Helpers;
@using Telerik.Sitefinity.Modules.Pages;
@model MyRatesViewModel
@Html.StyleSheet(Url.WidgetContent("kendoui/styles/kendo.common.min.css"), "head", false)
@Html.StyleSheet(Url.WidgetContent("kendoui/styles/kendo.default.min.css"), "head", false)
@Html.StyleSheet(Url.WidgetContent("kendoui/styles/kendo.bootstrap-v4.min.css"), "head", false)
@Html.Script(ScriptRef.JQuery, "head") <!-- required for Kendo to work -->
@Html.Script(Url.WidgetContent("kendoui/js/jszip.min.js"), "head") <!-- required for Excel Exports to work -->
@Html.Script(Url.WidgetContent("kendoui/js/kendo.all.min.js"), "head") <!-- required for Kendo MVC to work -->
@Html.Script(Url.WidgetContent("kendoui/js/kendo.aspnetmvc.min.js"), "head") <!-- required for Kendo MVC to work -->
<div class="row">
<div class="col-12">
<div>
<table style="overflow: auto; border-collapse: collapse; width: 100%; max-width: 600px;">
<tr>
<td style="border-right: #aca899 1px solid; border-top: #aca899 1px solid; border-left: #aca899 1px solid;">
<p>@Model.Message</p>
</td>
</tr>
</table>
</div>
@(Html.Kendo().Grid<MyWidget.Mvc.Models.MyRateClass>()
.Name("rategrid")
.AutoBind(false)
.Columns(columns =>
{
columns.Bound(p => p.Maturity);
for (int i = 0; i < Model.MaxTiers; i++)
{
var tier = i + 1;
columns.Template(p => { }).ClientTemplate(string.Format("#=kendo.toString(Rates['{0}'], \"0.00\")#", i)).Title(string.Format("Tier {0}", tier));
}
})
.ToolBar(toolbar =>
{
toolbar.Excel();
})
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Multiple)
.Type(GridSelectionType.Row))
.AllowCopy(true)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.PageSize(25)
.Read(read => read.Action("RetrieveRates", "Rates"))
)
)
</div>
</div>
<input type="button" onclick="myfunction ()" value="Load Grid">
<script type = "text/javascript">
function myfunction() {
var grid = $("#rategrid").data("kendoGrid");
grid.dataSource.read();
grid.refresh();
}
```
Clicking "Load Grid" will properly refresh the empty grid and cause it to display 2 rows when used in IE 11. The fact that this works in IE 11 and not in any other is a real head scratcher. Any assistance is appreciated!