I'm using KendoUI Grid to show data. I have server paging working like a charm. The each page change in the kendo grid is a new ajax request to the server and the server returns the correct page of data. I am now trying to do server-side sorting, but I'm having trouble getting model binding to bind to the sort values.
This is what the request from the Kendo Grid looks like:
My action method looks like this:
public JsonResult GetReports(int pageSize, int skip, List<KendoSort> sort)
{
// sort is not being populated with the right data.
}
KendoSort is a custom class:
public class KendoSort
{
public string Field { get; set; }
public string Dir { get; set; }
}
I know I'm not doing this right. How should my action method look to correctly capture the data supplied for the sort? The screenshot shows only a single item in the sort collection, but the grid could pass more. For example, it could also have included an additional sort:
sort[1][field]: reportName
sort[1][dir]: asc
Basically it would be saying "sort by id in ascending order, then by reportName in ascending order". How can I get this data into my action method without having to poke around in Request
and manually parse the parameters?
The ASP.NET MVC model binder does not understand expressions like sort[0][field]
. It understands only sort[0].field
which is unfortunate because jQuery.ajax
submits nested objects in the former format.
There are two ways to solve the problem:
- Use Kendo UI Complete for ASP.NET MVC. It comes with a built-in model for the grid request. More info can be found here.
Create a parameterMap and translate the sort expression:
parameterMap: function(options) {
var result = {
pageSize: options.pageSize,
skip: options.skip
};
if (options.sort) {
for (var i = 0; i < options.sort.length; i++) {
result["sort[" + i + "].field"] = options.sort[i].field;
result["sort[" + i + "].dir"] = options.sort[i].dir;
}
}
return result;
}
UPDATE FROM QUESTION AUTHOR:
I did end up using parameter map, but rather than re-structure the sort field I simply stringified the options and specified the contentType on the CRUD transports. The model binder knows to bind to the stringified JSON as long as the contentType is specified.
transport: {
read: {
url: '...',
type: 'POST',
contentType: 'application/json'
},
update: {
url: '...',
type: 'POST',
contentType: 'application/json'
},
destroy: {
url: '...',
type: 'POST',
contentType: 'application/json'
},
create: {
url: '...',
type: 'POST',
contentType: 'application/json'
},
parameterMap: function (options, type) {
return JSON.stringify(options);
}
}
I found an answer from another thread using IDictionary<string, string>[] sort
, which seems to be the most elegant and cleanest way to capture the sort criteria on the server side. I don't use a custom model binder as the sample code showed. I simply capture the sorting criteria using IDictionary array and then apply that criteria to my own data source. Here is the link to that discussion thread: Using IDictionary array to capture Kendo UI sorting criteria