1
votes

I have a SignalR 2.1.1 strongly-typed hub where the client is calling a server hub method and within that method a broadcast is sent to the clients (in my test case it is only the caller that is getting called).

The hub method has no return value (async public Task Test()). From the server side, the hub method appears to throw no exceptions. On the client side, I get Error: Failed at parsing response: {"C":"d-4336366B-A,0|B,1|C,2|D,0|E,0","M":[{ and Clearing hub invocation callbacks with error: Connection was disconnected before invocation result was received.

It appears the connection is getting terminated before the response is sent completely.

The problem is happening in Chrome on Windows 7 but not in IE 11.

Simplified Hub Class

public class MessengerHub : Hub<IMessengerClient>, IMessengerHub
{
    async Task IMessengerHub.TestActivityNotification()
    {
        ConnectionInfo info = _connectionInfo[_hub.Context.ConnectionId];

        Activity activity = new Activity
        {
            ActivityId = Guid.NewGuid(),
            ContactId = info.UserId,
            DateTime = DateTime.UtcNow,
            DeviceId = info.DeviceId,
            Kind = ActivityKind.Message,
            SubKind = ActivitySubKind.MessageSent
        };

        // This code is actually in another method, just simplifying for demo
        await Task task = Task.Run(() =>
            {
                // I thought the problem might be with the groups...
                //Clients.Group(userId.ToString()).OnActivity(activity);
                foreach (ConnectionInfo info in _connectionInfo.Values.Where(ci => ci.UserId == userId))
                {
                    Clients.Client(info.ConnectionId).OnActivity(activity);
                }
            });
    }
}

If I comment out the call to OnActivity above, the problem goes away.

JavaScript initialization code

This is from the Razor page so note the Razor syntax.

//-----------------------------------------------------------------------------
// SignalR Initialization
//-----------------------------------------------------------------------------

$(function () {

    // ------------------------------------------
    // Set up the client side of the hub
    // ------------------------------------------
    var messengerHub = $.connection.messengerHub;
    var hub = $.connection.hub;

    radarMessenger.hub = messengerHub;
    radarMessenger.signalr = {
        stateConversion: {0: 'connecting', 1: 'connected', 2: 'reconnecting', 4: 'disconnected'}
    };

    messengerHub.client.onActivity = radarMessenger.onActivity;


    // ------------------------------------------
    // Connect to the hub
    // ------------------------------------------

    @{
            Activity context = SecurityUtils.GetContext();
        }
    hub.qs = {
        deviceId: '@context.DeviceId',
        userId: '@context.ContactId'
    };

    hub.logging = true;

    hub.starting(function() { 
        console.log("SignalR: Starting"); 
    });

    hub.received(function(data) {
        console.log("SignalR: Received: " + JSON.stringify(data)); 

    });

    hub.connectionSlow(function() { 
        console.log("SignalR: Connection slow"); 
    });

    hub.reconnecting(function() {
        console.log("SignalR: Reconnecting"); 
    });

    hub.stateChanged(function(data) {
        console.log("SignalR: State changed from " + 
            radarMessenger.signalr.stateConversion[data.oldState] + " to " + 
            radarMessenger.signalr.stateConversion[data.newState] ); 
    });

    hub.disconnected(function() { 
        console.log("SignalR: Disconnected"); 
    });

    hub.error(function (error) {
        console.log("SignalR: Error: " + error ); 
    });

    hub.start()
        .done(function(){ console.log('Now connected, connection ID=' + hub.id); })
        .fail(function(){ console.log('Could not Connect!'); });

    $("#TestActivityNotification").click(function () {
        console.log('TestActivityNotification');
        messengerHub.server.testActivityNotification()
            .done(function () {
                console.log("Called testActivityNotification successfully");
            })
            .fail(function (error) {
                console.log("Error in testActivityNotification: " + error);
            });
    });
});

Chrome dev console

SignalR: State changed from disconnected to connecting 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:397
SignalR: Client subscribed to hub 'messengerhub'. jquery.signalR-2.1.1.js:81
SignalR: Starting 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:380
SignalR: Negotiating with '/securemessaging/signalr/negotiate?clientProtocol=1.4&deviceId=a60aea91-1d79-4881-943d-1fbf3cb8ba4e&userId=2deb491a-c4f6-4f99-b653-aac65450c3db&connectionData=%5B%7B%22name%22%3A%22messengerhub%22%7D%5D'. jquery.signalR-2.1.1.js:81
SignalR: Attempting to connect to SSE endpoint 'https://dev01.myradarconnect.com:13004/securemessaging/signalr/connect?tran…Uo10Wpetj&connectionData=%5B%7B%22name%22%3A%22messengerhub%22%7D%5D&tid=7'. jquery.signalR-2.1.1.js:81
SignalR: EventSource connected. jquery.signalR-2.1.1.js:81
SignalR: serverSentEvents transport selected. Initiating start request. jquery.signalR-2.1.1.js:81
SignalR: The start request succeeded. Transitioning to the connected state. jquery.signalR-2.1.1.js:81
SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332 and a connection lost timeout of 20000. jquery.signalR-2.1.1.js:81
SignalR: State changed from connecting to connected 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:397
Now connected, connection ID=64188d16-5abe-4e67-9393-10eb59862f82 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:411
TestActivityNotification 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:415
SignalR: Invoking messengerhub.TestActivityNotification jquery.signalR-2.1.1.js:81
SignalR: Error: Error: Failed at parsing response: {"C":"d-4336366B-A,0|B,1|C,2|D,0|E,0","M":[{ 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:407
SignalR: Stopping connection. jquery.signalR-2.1.1.js:81
SignalR: State changed from connected to disconnected 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:397
SignalR: EventSource calling close(). jquery.signalR-2.1.1.js:81
SignalR: Fired ajax abort async = true. jquery.signalR-2.1.1.js:81
SignalR: Stopping the monitoring of the keep alive. jquery.signalR-2.1.1.js:81
SignalR: Clearing hub invocation callbacks with error: Connection was disconnected before invocation result was received.. jquery.signalR-2.1.1.js:81
SignalR: messengerhub.TestActivityNotification failed to execute. Error: Connection was disconnected before invocation result was received. jquery.signalR-2.1.1.js:81
Error in testActivityNotification: Error: Connection was disconnected before invocation result was received. 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:421
SignalR: Disconnected 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:403
SignalR: Received: {"$id":"4","$type":"Microsoft.AspNet.SignalR.Hubs.HubResponse, Microsoft.AspNet.SignalR.Core","I":"0"} 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:384

Update 2014-09-24 Custom JsonSerializer

Based on the answer from @halter73, I am updating to say that I am indeed using custom JsonSerializerSettings. I'll mess with those and update. Here they are:

    private static void ConfigureJsonFormatter()
    {
        JsonSerializerSettings jsonSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
        jsonSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
        jsonSettings.Formatting = Formatting.Indented;
        jsonSettings.TypeNameHandling = TypeNameHandling.Objects;
        jsonSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
        jsonSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;

        JsonSerializer serializer = JsonSerializer.Create(jsonSettings);
        GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => serializer);
    }

I am using Entity Framework and needed to tweak some of the JSON serialization settings to avoid some issues with entity serialization, in Web API, MVC, and SignalR.

1

1 Answers

7
votes

Based on the following line in your log:

SignalR: Received: {"$id":"4","$type":"Microsoft.AspNet.SignalR.Hubs.HubResponse, Microsoft.AspNet.SignalR.Core","I":"0"} 105b20f2-2a6a-46da-83ae-35c32b82eba1?Archived=True:384

It looks like you are using a custom JsonSerializer. This can be problematic if you're not careful, because SignalR relies on some default behavior. For example, JSON payloads must be only one line to work with SignalR's server-sent events transport.

Chrome supports the EventSource API required to use server-sent events, but IE does not. This is likely why you are only seeing the issue with Chrome.