Just want to share this in case anyone else runs into it. When a Kendo UI grid is bound to a SignalR datasource and Batch = true for that datasource, the server will begin responding with the following during create/update/destroy method calls:
{
"I"
:
"1"
,
"E"
:
"There was an error invoking Hub method 'tranimporterrorshub.update'."
}
This is because the automatically generated JSON is in an incorrect format to bind to your hub methods.
Example hub method:
public
class
ExampleHub : Hub
{
public
DataSourceResult Read(DataSourceRequest request)
{
// read operations here
}
public
async Task Update(IEnumerable<ExampleViewModel> rows)
{
foreach
(var row
in
rows)
{
// Update operations here
}
}
public
async Task Destroy(IEnumerable<ExampleViewModel> rows)
{
foreach
(var row
in
rows)
{
// Delete operations here
}
}
}
When the JSON for create/update/destroy is generated, it is something like this:
data:{
"H"
:
"exampleshub"
,
"M"
:
"update"
,
"A"
:[{
"models"
:[{
"Id"
:1,
"Example"
:
"Test"
},{
"Id"
:3,
"Example"
:
"Test2"
}]}],
"I"
:2}
If you look closely, the "A" property in the JSON starts with a "[", which indicates an array, even though there is NOT an array of models. ASP.NET MVC SignalR does not support a call with the "data" being an array (must be an object or basic type) and the following exception is thrown:
Exception: Exception thrown: 'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.dll ("Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[ExampleViewModel]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<
T
>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'models', line 1, position 10.").
I found a fix for this. Simply add this function and wire it up to the parameterMap property for your DataSource:
function
datasourceParameterMap(data, type) {
if
(type !==
'read'
&& data.models) {
return
data.models;
}
else
{
return
data;
}
}
Hope this helps someone else so that they don't have to figure it out the hard way.