Making SignalR work in IE8 with Chrome Frame

On a recent project we have developed a single page type web application.

We chose to power it with knockoutjs and SignalR, which was a great idea except for one small caveat: the customers target environment was WinXP with IE8 and no option to upgrade to a more modern browser.

At first we had no problems. But then as the application grew, we realized that there is a reason why people used to claim that javascript MVC frameworks were too slow: They really ARE to slow, if you are running a browser from that day and age!

So, to the rescue came Google Chrome Frame (which, unlike a newer browser, the IT-departmit DID allow). Lo and behold, everything worked just fine again.

EXCEPT! SignalR was now broken :-( Not completely broken, mind you. SignalR can SEND events to the server, but not receive them.

It turns out that SignalR considers an IE8 with Chrome Frame to be an actual Chrome browser. Which is what you’d expect, I guess. Which also means that SignalR uses server sent events as its signalling protocol. But for some reason, that only works for messages going up to the server. Messages sent from server to client are not processed correctly.

Since it is not possible to do client-side detection that javascript is running inside a Chrome Frame, the solution has been to do a server side detection and set the transports object to only allow longPolling:

    var chromeframe = Request.UserAgent!=null && Request.UserAgent.Contains("chromeframe");
    var transports = chromeframe ? "{ transport: 'longPolling' }" : "";
    $.connection.hub.start( @( Html.Raw(transports) ) );

With this method, clients with Chrome Frame installed will always use longPolling and all other clients will use default SignalR behavior.


Leave a Reply