FIX: Grid with SignalR Binding Not Working with Batch on DataSource

2 posts, 0 answers
  1. Keith
    Keith avatar
    3 posts
    Member since:
    Nov 2015

    Posted 26 Jun 2017 Link to this post

    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.

  2. Keith
    Keith avatar
    3 posts
    Member since:
    Nov 2015

    Posted 26 Jun 2017 in reply to Keith Link to this post

    Small clarification.  The fix is still correct, but the reason for the issue is not the square brace in the beginning of the data, it's the extra "models" property added.  This is what is output by default (same as original post):

    data:{"H":"exampleshub","M":"update","A":[{"models":[{"Id":1,"Example":"Test"},{"Id":3,"Example":"Test2"}]}],"I":2}

     

    This is what SignalR in MVC needs:

    data:{"H":"exampleshub","M":"update","A":[[{"Id":1,"Example":"Test"},{"Id":3,"Example":"Test2"}]],"I":2}

     

    Note the removal of the "models" property.

Back to Top