How to deal with session left open
Asked Answered
A

3

7

I am implementing a session structure.

I have a ConcurrentDictionary on server side holding on to all the <SessionId, UserSession> pairs.

When a new connection is established a cookie is assigned to a client browser, perm or temp depending on the RememberMe option.

When clients call the LogOut function it removes the session from the dictionary.

However, when the client browser is simply closed or crashed, and cookie was lost or expired or deleted, the server side session object in memory is remained in dictionary and becomes a ghost. Over time these ghosts will stack up.

My question is, how to improve the design so that the dead sessions can be cleaned up after they are expired?

I thought about making a timer service running a cleaning schedule, but it feels not elegant. Is there a simpler way to do this without depending on an external service?

Absorbefacient answered 27/9, 2013 at 23:2 Comment(4)
It would be better to use a cache with a rolling term, or handle the Session_End method. What are you storing in UserSession?Inhale
There is no reliable Session_End method to handle, if client browser crashes, then it just ends there without talking back to server. But now that you mentioned a cache, I got an idea, I can store a list sorted by LastActive time. Whenever a new client logs in, he can help the check the earliest session in the queue and remove if expired. Every active user will put himself to the back of the queue when he call the server to do something. So, he becomes the latest active person.Absorbefacient
Do you at some point need to see data about everyone that's logged in? If not, why not just store your data in Session (if you need the data) and let it disappear after the session times out? That will handle memory pressure also by dropping items out of Session if there's pressure. Or use HttpContext.Cache with a rolling timeout, so it'll disappear after a set time after last access. (Basically, no need to roll your own.)Inhale
Turning the question on its head: Depending on your intent/goal for persistence, does moving persistence to client work?Folberth
C
5

i have similar situation in one of my project.

instead of dictionary, i used cache with a short absolute expiration and session id of user as my cache key:

HttpContext.Current.Cache.Insert(sessionID, userEntity, null, DateTime.Now.AddSeconds(30), TimeSpan.Zero);

and in the client side, i make an ajax call,every 15 seconds, to notify the server and renew the cache for that session id.

so whenever a user close his browser window, server doesn't recieve any notification and session id of user expired automatically.

Cairns answered 29/9, 2013 at 8:2 Comment(1)
Thanks, did some search following the idea, realised System.Runtime.Caching in .NET4 above seems to be the way to go. bartwullems.blogspot.com.au/2011/02/caching-in-net-4.htmlAbsorbefacient
P
3

If your sessionstate is "InProc", why not just apply your code in Session_Start and Session_End?

void Session_Start(object sender, EventArgs e)
{
    //Add to ConcurrentDictionary
}

void Session_End(object sender, EventArgs e)
{
    // Note: The Session_End event is raised only when the sessionstate mode
    // is set to InProc in the Web.config file. If session mode is set to StateServer 
    // or SQLServer, the event is not raised.

    //Remove from ConcurrentDictionary
}
Popliteal answered 29/9, 2013 at 8:22 Comment(0)
A
1

I am answering my own question after few months. If I want to have a structure like that, I would use Microsoft SignalR. Because it controls the sessions for me in a real time manner and does much more.

Absorbefacient answered 29/9, 2013 at 6:53 Comment(1)
Why are you still using Sessions for authenticating users. This method was a viable solution for classics ASP era but not anymore. You should considering using ASP.NET Forms authentication instead which is a preferred approach in ASP.NET World.Vadnee

© 2022 - 2024 — McMap. All rights reserved.