We have a web application that uses SignalR for its notification mechanism.The problem is when we are browsing our web application using IE ,SignalR uses Long Polling as its transport type thus sends back requests to our web server therefore Session never expires no matter how long the browser is idle.
We were thinking that maybe we could catch the requests in Global.asax and see if they were from SingalR and set the session timeout to the remaining time (Which I don't think it's a straightforward solution).
Is there any other solution the we are missing ?
It's more stable and maintainable -in my view- to have your own "session like timeout" . Set your .NET session timeout to infinity since you'll not be using it and then create a global JavaScript counter (in your layout or master page) to track the time passing while the browser is idle (obviously
setTimeout
orsetInterval
every few seconds would do the trick). Make sure to have the counter reset on every web request (that should happen automatically since all JavaScript variables would reset). In case you have pages that depend on web services or Web API, make sure to reset your global JavaScript counter on every call. If the counter reaches your desired timeout without being reset, that means that the session is expired and you can logout the user. With this approach you'll have full control over the session lifetime which enables you to create a logout timer popup to warn the user that the session is about to expire. SignalR would perfectly fit with this approach since the JavaScript timer would keep ticking.If you take a look at the description of the SignalR protocol I wrote a while ago you will find this:
» ping – pings the server ... Remarks: The ping request is not really a “connection management request”. The sole purpose of this request is to keep the ASP.NET session alive. It is only sent by the the JavaScript client.
So, I guess the ping request is doing its job.
I here post @Simon Mourier's commented solution, with his approval, as a CW answer, as I find the suggested approach the most appropriate and less intrusive, as it just disables the Session for SignalR requests.
A positive side effect is that the request will be processed faster as the Session object doesn't need to be initiated and loaded.
It still uses a IHttpModule for the work, and the preferable place is likely the AcquireRequestState event (not personally tested yet though), or at an event raised earlier, before making use of the Session object.
Do note using this approach that one might need to test that the Session object is available before access any of its members or stored objects.
Here is another completely different approach, simple, yet quite efficient.
Instead of relying on Session/Auth cookies to decide whether a user has timed out, use the Cache object. This have more or less no side effects and work just like if the user simply logged out.
By simply add this small snippet somewhere in the beginning of your web app code, where of course SignalR don't go, you will be able to check if the cache item is there and reinitiate it (with the same expiration time as the Session timeout is set), and if not, just do a logout and remove cookies/session variables.
And within your user login method, you just add this, to create the cache item for the first time
The workaround I am currently using is an IHttpModule to check if the request is a Signalr request, if so remove the authentication cookie, this will prevent the ASP.net session timeout from being reset, so if your Session Timeout is 20min and the only requests are Signalr the users session will still timeout and the user will have to login again.
I feel this is a real hack solution so would love so other ideas to prevent session timeout renew when data is pushed to the client from the server, or a when javascript client polls an endpoint for data.