hbulens
hbulens

Reputation: 1969

SignalR freezes at 'Initiating start request'

I am experiencing the strangest behavior with SignalR. After some refactoring I encountered issues with connectivity. I think it was pure luck that made it work before as the code didn't comply to the recommended practices. For instance I started the hub before I declared the hub methods (as explained by David Fowler) so the client never explicitly subscribed to those hubs but somehow they did. I have looked all day why and how but no luck.

After refactoring this is the code that is executed once the document is loaded:

function initSignalR() {
   var me = this,
    appointmentHub = $.connection.appointmentHub,
    assignmentHub = $.connection.assignmentHub,
    taskHub = $.connection.taskHub,      
    notificationHub = $.connection.notificationHub,
    messageHub = $.connection.messageHub;

  $.connection.hub.connectionSlow(onConnectionSlow);
  $.connection.hub.stateChanged(onStateChanged);
  $.connection.hub.error(onError);
  $.connection.hub.disconnected(onDisconnected);
  $.connection.hub.logging = true;

  appointmentHub.client.updateAppointment = onUpdateAppointment;    
  $.connection.hub.start().done(onDone).fail(onFailed);
   ... code ommitted for brevity ...
}

function onUpdatedAppointment(appointment) {
 .... code ommitted for brevity ....
}

These are the logs that appear in the console when it occassionally works:

Client subscribed to hub 'appointmenthub' Negotiating with '/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22appointmenthub%22%7D%5D' webSockets transport starting. Connecting to websocket endpoint 'ws://localhost:52541/signalr/connect?.... Websocket opened. webSockets transport connected. Initiating start request. The start request succeeded. Transitioning to the connected state. Now monitoring keep alive with a warning timeout of 13333.333333333332, keep alive timeout of 20000 and disconnecting timeout of 30000

I wrote 'occassionally' on purpose because every now and then SignalR connects correctly. Sadly however most of the time I don't get that far. Usually the last visible step in the console is :

webSockets transport connected. Initiating start request.

For some time I thought it was the body of the callback method that caused the issue I could connect more when I had an empty function but even that isn't the cause. So I'm running out of ideas what to do next.

For the sake of completeness, here is the startup code in ASP.NET MVC:

GlobalHost.Configuration.TransportConnectTimeout = TimeSpan.FromSeconds(50);
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(110);

GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule());    
GlobalHost.DependencyResolver.Register(typeof(IJavaScriptMinifier), () => new SignalRMinifier());
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => new UserIdProvider());

HubConfiguration hubConfiguration = new HubConfiguration()
{                 
   EnableDetailedErrors = true,  
};

return app.MapSignalR(hubConfiguration);

I found a similar issue but no solution has been provided there.

I tested this in IE/Edge/Chrome/Firefox/Opera and all have the same results. The application is running on ASP.NET MVC5 and the latest version of SignalR (2.2.1) is used.

Upvotes: 0

Views: 683

Answers (1)

hbulens
hbulens

Reputation: 1969

So it turns out there was nothing wrong with the client side code or the configuration of SignalR, but the problem was situated in the Hub class.

I had some custom code in the OnConnected method which was causing timeouts and/or errors (connections to external services and databases were made there). By dispatching the work to a different process (e.g. using Hangfire or NServiceBus) I was able to fix the issue as mentioned before.

In hindsight the described behavior makes total sense. The lesson I learned here is to treat Hubs like controllers in ASP.NET MVC: they should be fat free and should contain limited business logic.

Upvotes: 1

Related Questions