Skip navigation.

Con 2.0All recent postsJeeves Departs

Session Q&A

Session storage has been around for so long that we take it for granted. However, working with the Session object has some nuances you don’t see documented in books. In this Q&A post I’d like to go over some issues you need to be aware of when relying on Session for short-term storage.

To limit this discussion to a reasonable scope, let’s assume we use only in-proc sessions. Storing session data in an out-of-proc state service or SQL Server is a different can of worms. Also, we won’t be talking about cookie-less sessions. They are a very strange beast.

One final disclaimer. I’m focusing on 1.x and realize that 2.0 has some enhancements some of which I will mention.

Q: Where is session ID stored?

A: When you first hit an ASP.NET-powered site, a non-expiring cookie with the name of ASP.NET_SessionId is issued (in 2.0 you can set a different cookie name in web.config). This cookie contains a randomly generated 20-something-character string which is the session ID and is sent with every request.

Here’s a very important point: the cookie will stay alive until you close your browser. In other words, the session ID will remain the same even if you navigate away to another site, say to check team standings at the Olympics, and then come back: if it’s the same browser window, the cookie will still be there and the session ID will be the same.

It’s possible to ditch a session by calling Session.Abandon() which will finish processing the page and only then clear out the session data. A subsequent page request causes a brand new session object to be instantiated. The session cookie is a staunch one—it stays intact even when Session.Abandon() causes one session object to die and another one to be born.

You can also let a session expire. The timeout interval is set in the <sessionState> section of web.config. When a session times out, it flushes all session data, the session object dies and a new one is born on a subsequent page hit. This is similar to the scenario with Session.Abandon() above. Even in this case the session cookie stays intact.

So here’s the conundrum: a session, essentially, is the time between the first page hit and the time when the browser window is closed. The fact that you can’t disable session timeout makes no sense to me. Basically, a user keeps his/her browser window open, but the session data may disappear due to a timeout. I wish there was a way to just let the session live for as long as the user has the browser running. Otherwise you end up with a predicament explained in the following section.

Q: Is there a way to tell if the session timed out or was abandoned?

A: There’s no simple answer to this. HttpSessionState has a handy property, IsNewSession which indicates whether the session was created with the current request. In other words, if you called Session.Abandon() or let it time out, your old session data will be gone, you will receive a brand new session object and Session.IsNewSession will be true the first time you hit a page.

I don’t know if it’s possible to tell which of the two things happened. Bob Boedigheimer shows how to at least detect session timeouts. I even rolled his code into a base class property to guard for this edge case.

The important point here is that you can never assume that if you’re stored something in session, it’ll be there the next time you go looking for it. A user may simply walk away from the computer and cause your session to expire. Again, these session timeouts seem nonsensical to me, but I don’t know if it’s possible to turn them off. Most likely not.

What you need to remember is to use code similar to Bob’s to detect if the session is gone. At this point you have two options:

  • re-read data and store it back in session, or
  • redirect to some page which politely notifies of the timeout and suggests to go back and do whatever the user was previously doing.

Q: Does presence (or absence) of global.asax affect the session ID?

A: Yes. Suppose you create a brand new web project without global.asax. After all, it’s perfectly normal to leave this file out if you don’t need it. Without global.asax your session cookie will be killed at the end of each page request, and a new one created on every subsequent request. This is to say the session ID will change with every page hit.

Now, suppose you add a blank global.asax. Does this help? No. The session ID will still change until you add an empty Session_Start() handler. If you dig long and hard with Reflector, you’ll see why the mere presence of this particular event handler guarantees that the session cookie will remain intact once it’s issued on first page hit.

Q: I don’t want global.asax in my project. Is there something I can do about the flaky session ID?

A: If you don’t want to drag around global.asax and need to "lock in" a session ID, your landing page needs to store something in session.

Here’s an example. Page a.aspx has no dealings with the session. Page b.aspx, on the other hand, stores something in session at least once. As long as you hit a.aspx, the session ID will change. As soon as you navigate to b.aspx, the session ID will "lock in" and remain constant until you close the browser.

To learn about the mechanics of it point your Reflector to the SessionStateModule class. MSDN has more on this, too:

When using cookie-based session state, ASP.NET does not allocate storage for session data until the Session object is used. As a result, a new session ID is generated for each page request until the session object is accessed. If your application requires a static session ID for the entire session, you can either implement the Session_Start method in the application’s Global.asax file and store data in the Session object to fix the session ID, or you can use code in another part of your application to explicitly store data in the Session object.

Q: The session cookie seems to be very resilient. Still, is there a way to discard it and obtain a new session ID?

A: The session cookie is a die-hard indeed. Microsoft’s Knowledge Base article How and why session IDs are reused in ASP.NET shows a dirty hack which forces the session ID to change. Don’t try this at home.

Q: When is Session_OnEnd called?

A: The runtime invokes Session_OnEnd, which you declare in global.asax, when you call Session.Abandon() or the session times out.

This leads to an interesting implication: does the session end immediately when the browser is closed (and, consequently, the session cookie goes away)? No, there’s no reliable way to detect when the user closes his/her browser.

The session manager stores session data in HttpCache with a sliding expiration. This expiration timeout is set in the <sessionState> of web.config. When the browser window is closed, the session is bound to expire because there’s no way to go back to using the session ID that just went away (unless you spoof the session, but we won’t discuss a movie-plot terrorist threat).

When the timeout is up, HttpCache will remove the session state object and invoke a callback which, essentially, translates into calling Session_OnEnd. Note that this happens way after the browser window is closed, but it does happen. Remember, you cannot access HttpContext is this handler, but the outgoing Session object is still alive. If you need to do some clean-up, Session.SessionID is still available.

Further Reading

There’s a great article by Michael Volodarsky at MSDN entitled Fast, Scalable, and Secure Session State Management for Your Web Applications which I highly recommend as a crash course in session management. Pay attention to the idea of "flattening" session data and breaking it down to storing only primitives. The discussion of partitioning and securing session state is very educational too.

One of the most important points of this article follows below:

Note that if you turn off session state in your application, the HttpContext.Session property will throw an exception if the page or handler tries to access it. If you mark the page as read-only, updates to the session in the out-of-process modes will not be preserved across requests. In InProc mode, however, updates will be preserved because they are made to the live objects that stay memory-resident across requests.

In other words, if you retrieve an object from Session and change any of its properties, you modify a live object and these changes are "committed" to the session even if the session is marked as read-only!

Conclusion

This improvised Q&A session is something I’ve been dealing with lately. I spent many hours Reflect’ing and experimenting, and figured I’d share my observations. Session state is a very helpful storage, but it will break you if you abuse it.

Comments

Comment permalink 1 Jingaling |
holy cow! you have to be kidding! if this is the kind of information on this site, i'll make sure to avoid it from now on.

"Again, these session timeouts seem nonsensical to me, but I don’t know if it’s possible to turn them off. Most likely not."

so you just want session info to stay around forever? don't you think that would tax memory just a tad? oh wait, you want to get rid of it when the user closes their browser. and how exactly do you expect to know about that on the server? and what about security? you want all those sessions just hanging around to be hijacked. Wow!
Comment permalink 2 Milan Negovan |
I'm speaking from a pragmatic point of view. We've run into plenty of problems trying to keep up with session time-outs. Apparently, you've never dealt with these issues.

If you plan on leaving other comments showing lack of proper respect, then yes---I'm afraid you'll have to avoid this site. Comments, offensive toward me or other readers/posters, get deleted.
Comment permalink 3 bhushan |
how can i clear session data if all i have is session ID?
Comment permalink 4 Milan Negovan |
See if KB 899918 answers your question.
Comment permalink 5 rameshbabu |
Hi,its veryhelpful for me,and also I have a problem with session_end while closing the browser.
Actually my requirement is show the online users in my website.if the user closed browser without logout also session_end have to fire.It working in my local system.But not working in remote.is need to changes any configuration settings in web.config or machine.config?
Comment permalink 6 TurboBH |
My web app use session to store some objects, but sometime when I refresh the webpage, the session data lost and session.IsNewSession change to "True" while the the session.sessionID does not change.

Do you known why?
Comment permalink 7 Mehul |
Hi,
This post is very helpful.
I am facing some problem with HttpContext.Session.IsNewSession property.This property works fine with request made to managed content(.aspx page).But when i make request to unmanaged content
(any image) this property returns null.

Is it the case that HttpContext.Session is not avilable for request made to unmanaged content.

Any inputs on this would be very helpful.
Comment permalink 8 Milan Negovan |
If you're doing it inside of a custom HTTP handler, you need to mark it with the IRequiresSessionState interface.
Comment permalink 9 Bhanu |
Hi,

I have used the method session.abandon() in a web service and i'm calling it in the client side function with Pagemethods using script manager tag but still it is not firing the event session_end. I'm unable 2 understand y its not getting fired. Please help me out.

Thanks in advance...
Bhanu
Comment permalink 10 Josh Stodola |
No matter what I do, Session_End will not fire on our production IIS server(s). Yes we use InProc, yes we have data in the session. The servers are not exactly top notch, they are running windows 2000 with IIS 5.1. In development, I can get the Session_End event to fire as expected. But as soon as I get it on IIS, it does not do anything.

I have scoured Google, many forums and news groups, and I am reading all the same junk over and over. Since it works in developement, I have to assume that IIS is the culprit. But, I have no idea what it could be.

Any ideas?!
Comment permalink 11 Milan Negovan |
Josh, has this article been of any help?
Comment permalink 12 Suresh Gopalakrishnan |
Is there a way to abandon the session for my application when navigating to another site without closing the browser?
Comment permalink 13 Milan Negovan |
There's Session.Abandon() but I've had problems with it in the past. There was something with it messing up my logout routine, so I use Session.Clear() instead.

Emails and Notifications

Would you like to be notified when somebody responds to this post?  Would you like to have these comments emailed to you?

TrackBacks

Sorry, TrackBacks are not allowed.

Submit your comment

Please enter only text since all HTML tags except hyperlinks will be stripped. Hyperlinks will become live links. Any comments with flaming or offensive language will be deleted. Be courteous to other posters. Thank you.

Your name (required):
Your email (optional):
Your site's URL (optional):
Enter this number
Type in the number above:
Comment (required):