The Question
Whilst browsing StackOverflow, I came across an old unanswered question from Feb 10 which caught my eye.
At first, I was quick to dismiss it as nonsense, but then I started looking into it further and became interested. It seems a lot of people are reporting an issue whereby Session_End
is sometimes called immediately after Session_Start
.
This can be reproduced in .NET 2.0/3.5 using the following steps:
- Create a new .NET 2.0 WebForms WebApplication
- Configure session for InProc, and set the timeout to 1 minute
- Add a break point on
Session_Start
and Session_End
events
- Debug the application and F5 to skip the first
Session_Start
break point
- Wait until the
Session_End
fires after 1 minute
- Refresh the browser, and notice
Session_End
is called immediately after Session_Start
- Note that adding a session variable to the page
OnLoad
solves the issue
According to documentation, there are 2 activities that can cause the Session_End
event to fire.
- When
Session.Abandon()
is called
- Immediately after the
Session
expires
In this example, neither are true
. So how can this be?
The Answer
Doing some research on the internet, I found a clue in a blog post on session state. It revealed an interesting quirk about how session state is handled.
This is that ASP.NET will only create a new InProc
session if the session is actually used by the application. If not, then the session is not persisted, and it will not even issue a session cookie (where it doesn't already exist).
So here's what's happening.
When the browser is refreshed after the session timeout, the old session cookie is sent in the request. This causes ASP.NET to reuse the original session ID for a new session. However because at the end of the request the application has not yet used the session, ASP.NET effectively abandons it to avoid persistence and to free resources. This causes an early Session_End
event.
Now because ASP.NET does not actually delete the pre-existing session cookie, every subsequent request is essentially restarting the session ID and repeating the sequence of events, such that Session_Start
/Session_End
are fired repeatedly until either the session is used or the cookie deleted.
The Fix
The issue has already been resolved in .NET 4.0. I suspect the session now remains persisted in the case of a session restart.
If your application is using .NET 2.0/3.5 and has expensive code hooked into the session start/end events, then I recommend you add a dummy session variable to your session start routine. This solves the problem by flagging the session as in use, and helps protect your server resources from excessive session events.