Unexpected Signalr connection abort in Firefox - asp.net

I am using SignalR (with cross-domain request), version 2.3.0 for webchat integrated to ASP.NET site. Everything is working fine. But I found strange behaviour of SignalR connection. When I clicked to the reference from tab of the chat for file downloading SignalR connection was aborted and onDisconnected method was triggered in my Hub class. FireBug show me next POST-request:
http://*:81/signalr/abort?transport=longPolling&clientProtocol=1.4&token=eUpLNitKcmR1d2JhTTRvcHNVZmEwcG1EKzYvMElZbmg4aE5yam9xM3k0dz0_IjAsNGJmOWNhODUtNDU2NS00NWExLWFjMTgtNzgyN2FhZDA2Njg1LGxvY2FsaG9zdCI1&State=1&connectionToken=hDXe9xIZtmrapjl1LRwtK9B%2BfYMoeuHka8ctBLaPa0YnjiN9iiFa%2BvFMBHIGpGH0h8qPEDgGZSRGwjMw3Wm1DJi6cUPtZjLca6%2FR2576SGksLAj3lnPN1JWIlxMsn8%2Bf&connectionData=%5B%7B%22name%22%3A%22c%22%7D%2C%7B%22name%22%3A%22voip%22%7D%5D, where * is my domain.
It is reproduced in Mozilla Firefox (version 30.0) for LongPolling or Websocket transports. How I can fix this problem? Or is it bug of SignalR or Firefox?

This bug has been recently filed against SignalR on GitHub. The basic idea is that downloading a file causes Firefox to trigger the window.onbeforeunload event which in turn causes SignalR to close any ongoing connections.
For now, the workaround is to attach a handler to the client's disconnected event that will call $.connection.start again after a short window.setTimeout.
You could also unbind SignalR's onbeforeunload handler: $(window).unbind("beforeunload"). The downside of doing this is that Firefox might not gracefully disconnect when the user leaves the page running SignalR. Without a graceful disconnect, SignalR will wait over 30 seconds before it times out the client and calls the OnDisconnected handler on the Hub or PersistentConnection.

I have managed to use the workaraound explained by halter73 and I have solved the issue described by dudeNumber4 resetting the connectionid inside the disconnect event so that the server kept calling back the right users based on their connectionid without the need to address them by their user or group names.
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start().done(function () {
$("#mySignalRConnectionIdHidden").val($.connection.hub.id);
});
}, 3000);
});

Related

SignalR client disconnected on Azure slots swap

I have web app on Azure with 2 slots.
Whenever the slot swap happens, all SignalR clients are disconnected and not even notified about the connection loss.
SignalR events such a Close, Error, Reconnected are never fired on the client.
How to prevent this or at least know when disconnect happens? (of course I need to avoid polling)
How to prevent this or at least know when disconnect happens?
We could enable SignalR tracing to view diagnositc infomration about events in your SignalR application. How to enable and configure tracing for SignalR servers and clients, we could refer to this document.
Detecting the reason for a disconnection
SignalR 2.1 adds an overload to the server OnDisconnect event that indicates if the client deliberately disconnected rather than timing out. The StopCalled parameter is true if the client explicitly closed the connection. In JavaScript, if a server error led the client to disconnect, the error information will be passed to the client as $.connection.hub.lastError.
C# server code: stopCalled parameter
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
if (stopCalled)
{
Console.WriteLine(String.Format("Client {0} explicitly closed the connection.", Context.ConnectionId));
}
else
{
Console.WriteLine(String.Format("Client {0} timed out .", Context.ConnectionId));
}
return base.OnDisconnected(stopCalled);
}
JavaScript client code: accessing lastError in the disconnect event.
$.connection.hub.disconnected(function () {
if ($.connection.hub.lastError)
{ alert("Disconnected. Reason: " + $.connection.hub.lastError.message); }
});
More details we could refer to Detecting the reason for a disconnection.
How to prevent this?
We could continuously reconnect it.
In some applications you might want to automatically re-establish a connection after it has been lost and the attempt to reconnect has timed out. To do that, you can call the Start method from your Closed event handler (disconnected event handler on JavaScript clients). You might want to wait a period of time before calling Start in order to avoid doing this too frequently when the server or the physical connection are unavailable. The following code sample is for a JavaScript client using the generated proxy.
$.connection.hub.disconnected(function() {
setTimeout(function() {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
});
More details we could refer to How to continuously reconnect

Signalr server messages to client cancelled (specific clients only)

I use signalR to display currently connected users. Some clients are failing to see the connected clients because the server to client connection is being cancelled by the client as shown below:
Below is my js code:
var progressNotifier = $.connection.activeConnectionsHub;
$.connection.hub.start().done(function () {
progressNotifier.server.showActiveConnections();
// code here
});
// client-side sendMessage function that will be called from the server-side
progressNotifier.client.addConnections = function (param) {
// code here never gets called
}
This only happens on some client browsers.
I tried disabling antivirus, firewall, malware etc. But it is still not working.
Does anyone have an idea what is causing this issue?

Firefox SignalR connection dies

Using Visual Studio 2015, ASP.NET MVC web application, SignalR 2 with jquery signalR 2.1.2. One simple hub, nothing fancy in my configuration:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
Here is the (working on 2/3 browsers) client code:
$.connection.hub.logging = true;
$.connection.hub.start().done( function () {
connectionId = $.connection.hub.id; // posted up
} );
uploadHub = $.connection.uploadHub;
$.extend( uploadHub.client, {
exportFilePrepared: function (){
$( '#exportWait' ).modal( "hide" );
}
});
I have a page where downloadable files are requested. When the post is made I'm showing a spinner overlay. After the file has been built on the server, I'm calling a client function via SignalR to hide the overlay.
Browser results with logging on the client turned on:
IE: Works. Messages from SignalR:
Keep alive has been missed, connection may be dead/slow.
Keep alive has timed out. Notifying transport that connection has been lost.
Updating iframe src to 'host/signalr/recconnect?transport=foreverFrame...
Triggering client hub event 'exportFilePrepared' on hub 'UploadHub'
Chrome: Works. Only message from SignalR:
Triggering client hub event 'exportFilePrepared' on hub 'UploadHub'
Firefox: Doesn't work. Messages from SignalR:
Stopping connection.
EventSource calling close().
Fired ajax abort async = false.
Stopping the monitoring of the keep alive.
If I put a breakpoint on the log message "Stopping connection" above in firefox, it never hits. Any clues how to further debug this?

what is the best design to use connections in signalr

I have some doubts regarding my software design with signalr,
usually I start with this code:
var connection = $.hubConnection();
var notifier = connection.createHubProxy('notifier');
connection.start()
.done(function () {
//alert('connection was succesful');
// your event handlers
});
UPDATED QUESTION
If you have a common click event handler that will only use signalR to broadcast a message, and this event handler is on a separate javascript file (out of the context of the current connection):
should I open the connection in the external script? or
should I send a reference of the proxy (already connected) to the external script?
When your page doesn't need a connection you should not open one.

Abort Asynchronous Web Service Call and redirect to another URL (ASP.NET Ajax)

In my webapp, I have a list of links generated from code-behind and bound to a repeater control. Clicking on a link opens a popup window, where, along with displaying some data, an asynchronous call to a WCF Service is made (through a javascript proxy). This service in turn calls another third party web service that might take a long time to respond. I am working with IE6, thats a unavoidable requirement.
Now, I abort this service on onunload if the user decides to not wait for the call to complete and just closes the popup window. The problem is, if the user clicks another link from the repeater immediately after, the new popup window opens but doesn't load the page (doesn't go to the supplied URL) till the previous asynchronous call has completed (I have verified this through Fiddler). Interestingly, this only happens for links within the same domain. If I change the link for one of the popus to, say, www.google.com, then the window opens and goes to the correct url as intended. But, for popups with links within my own domain, which are opened immediately after a popup window with an unfinished request was closed, it waits till the previous request completes before loading the url.
I have verified the correct way to abort a callback and abort does fire properly. I also know that I can only abort my client side call, and not the server side call and I don't care about it. My only requirement is that the browser load the next link regardless of the previous asynchronous response.
//Method to Call Service:
function GetData(Id) {
//call the service
Sys.Net.WebRequestManager.add_invokingRequest(On_InvokingRequest);
var service = new WrapperService();
service.GetData(Id, handleSuccess, handleError, null);
Sys.Net.WebRequestManager.remove_invokingRequest(On_InvokingRequest);
}
//method to get the current requests abort executor
function On_InvokingRequest(executor, eventArgs) {
var currentRequest = eventArgs.get_webRequest();
abortExecutor = currentRequest.get_executor();
}
//abort service on unload
function unload() {
if (abortExecutor != null) {
abortExecutor.abort();
}
}
Helpful/Similar links for the background:
browser-waits-for-ajax-call-to-complete-even-after-abort-has-been-called-jquery
aborting-an-asp-net-web-service-asynchronous-call
canceling-ajax-web-service-call
Anybody faced this before? Its driving me nuts! Any help will be greatly appreciated.
The answer in one of your links sounds like the problem to me:
Browser waits for ajax call to complete even after abort has been called (jQuery)
Does your service require session state?
You could prove whether the problem is that IE itself won't issue the request by configuring IE to allow for more than 2 requests to the same domain. If it's being blocked because the aborted request is somehow eating up one of those connections, then increasing it should yield different results. If it still has the problem, it must be that the server is waiting to respond.
Configure IE for more than 2 requests:
http://support.microsoft.com/kb/282402
Quote from one of the SO questions you linked:
It turns out I was completely wrong about this being a browser issue - the problem was on the server. ASP.NET serializes requests of the same session that require session state, so in this case, the next page didn't begin processing on the server until those ajax-initiated requests completed.
Unfortunately, in this case, session state is required in the http handler that responded to the ajax calls. But read-only access is good enough, so by marking the handler with IReadOnlySessionState instead of IRequiresSessionState, session locks are not held and the problem is fixed.

Resources