Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR connection freeze other ajax requests

I develop an asp.net mvc application with the real-time messaging system based on the SignalR (jquery.signalR-2.0.0-beta2.js). The problem is that all partial views cannot be loaded after the SignalR connection started. In this case all ajax requests after the $.connection.hub.start({ transport: 'longPolling'}).done(function () { applicationHub.server.connectUser(); }) stay in pending state. Is it posible to make this requests async or is it a bug in the SignalR? Thanks for your help!

SignalR call:

<script type="text/javascript">

    $(document).ajaxStop(function () {
        var applicationHub = $.connection.applicationHub;

        if ($.connection.hub && $.connection.hub.state == $.signalR.connectionState.disconnected) {

            registerConversationClientMethods(applicationHub);

            $.connection.hub.start({ transport: 'longPolling'}).done(function () {
                applicationHub.server.connectUser();
            })
            .fail(function () {

            });
        }
    });
</script>

Ajax call which renders a partial view:

function LoadActivities(id, type, container, action, loaderpath) {

var url = action + '/?id=' + id + '&type=' + type;
var targetDiv = container;
var ajaxLoading = "<img id='ajax-loader' src='" + loaderpath + "' height='6' width='50' style='margin:5px;'>";

$(targetDiv).html("<div align='center'>" + ajaxLoading + "</div>");

$.get(url, null, function (result) {
    $(targetDiv).html(result);
});

}

like image 911
Alliancer Avatar asked Jul 23 '13 14:07

Alliancer


2 Answers

I have another explanation for what might have caused the problem.

Since the question was asked in 2013 I assume that the author already found the solution for his problem. But since it took me several hours to dig into mine, I believe it is my duty to share my experience.

Architecture overview: Asp.Net SPA application with AngularJS on client side and WebApi 2.0 and SignalR 2.1 on server side.

Problem symptoms: the application starts and functions normally but after some while all requests (SignalR and WebApi) get stuck. By 'stuck' I mean that WebApi requests are being made on the client but controller methods never get called. The first one to get frozen is always the SignalR request.

Network Monitor

After doing some search I've found the most probable reason for these symptoms. This was the "Session State Blocking" issue described in detail in this post by John Culviner.

Since my application was not using sessions I simply switched them to read-only mode on application level:

protected void Application_Start()
{
    // Some extra initialization here
    Context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}

This did not help.

I continued my research and I believe that by that time I've read every article or bug report with keywords SignalR, connection, stuck, freeze, hang. Nothing seemed to be related with my case. So instead of searching what might be the problem with the technology in use, I started to analyze what might be wrong with my own code. And there it was.

My problem has a good description in this article by Shaun. Here is the overview. In standard MVC world SignalR manages its connection itself. It will disconnect itself automatically when you move to another page. So you could just create the connection and forget about it. Unfortunatelly this is not true for SPA/AngularJS applications. SignalR connection will never know that the page inside SPA was changed and will never disconnect itself. When you return to the page a new SignalR connection will be created. In my observations you need to do this around 10 times to make the pipe that serves the requests stuck.

So all you have to do here is creating a stop function for SignalR connection and calling it manually before changing the page inside SPA:

stop: function() {
    if (connection && connection.state && connection.state !== 4 /* disconnected */) {
        connection.stop();
    }
},

In controller:

$scope.$on('$destroy', function() {
    clientPushHubProxy.stop();
});
like image 86
user1921819 Avatar answered Nov 13 '22 16:11

user1921819


Taking @bjornhol's answer a little further - the same issue of all SignalR requests (which were loading more AJAX) queuing up was happening to me too. I thought it was jQuery which was the issue but in actual it is the session state. For that controller if you can set the SessionStateBehaviour to ReadOnly or Disabled you will see the requests go through simultaneously. Please see this link too http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/ Hope this helps.

like image 44
Freelancer Avatar answered Nov 13 '22 17:11

Freelancer