在Chrome中,当集线器代码广播到客户端时,SignalR 2.1.1集线器客户端到集线器方法会提前终止连接

时间:2014-09-23 19:16:26

标签: signalr signalr-hub

我有一个SignalR 2.1.1强类型集线器,其中客户端正在调用服务器集线器方法,并且在该方法中,广播被发送到客户端(在我的测试用例中,它只是被调用的调用者)。

hub方法没有返回值(async public Task Test())。从服务器端看,hub方法似乎没有异常。在客户端,我得到Error: Failed at parsing response: {"C":"d-4336366B-A,0|B,1|C,2|D,0|E,0","M":[{Clearing hub invocation callbacks with error: Connection was disconnected before invocation result was received.

在完全发送响应之前,连接似乎已终止。

问题出现在Windows 7上的Chrome中,但不会出现在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);
                }
            });
    }
}

如果我注释掉上面对OnActivity的调用,问题就会消失。

JavaScript初始化代码

这是来自Razor页面所以请注意Razor语法。

//-----------------------------------------------------------------------------
// 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开发者控制台

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

更新2014-09-24自定义JsonSerializer

根据@ halter73的回答,我正在更新说我确实使用自定义JsonSerializerSettings。我会搞砸那些并更新。他们在这里:

    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);
    }

我正在使用Entity Framework,需要调整一些JSON序列化设置,以避免Web API,MVC和SignalR中的实体序列化问题。

1 个答案:

答案 0 :(得分:7)

根据日志中的以下行:

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

看起来您正在使用自定义JsonSerializer。如果您不小心,这可能会有问题,因为SignalR依赖于某些默认行为。例如,JSON有效负载必须只能使用一行来处理SignalR的server-sent events传输。

Chrome支持使用服务器发送事件所需的EventSource API,但IE不支持。这可能是您只看到Chrome问题的原因。