Tuesday, December 8, 2009

Global.asax Session_End NullReferenceException

I had an issue pop up on an ASP.NET web app this morning consisting primarily of NullReferenceExceptions being thrown when Global.asax runs some cleanup code from its Session_End handler. Basically, the cleanup code is disposing some IDisposable items stored in session state before the session blinks out of existence. The manner in which the session was being accessed was the following:

System.Web.HttpContext.Current.Session[...

This throws a NullReferenceException since HttpContext.Current is null. Null? Why is the context null? It didn't seem logical at first, but after a minute of thought, it came to me. Of course there's no context, the session expires on a timeout. Although, the lifecycle of a session begins with a request, it doesn't end with one. Thus, when a session times out there is no request or response available, and thus no context.

Well, how do I access the session then?

Easy. Global.asax has a Session property. It is not null at this point, and this allows you to work with the session before the session is garbage collected. I had to change my cleanup code interface, but I the resolution consisted of Global.asax passing the session to the cleanup code rather than having the cleanup code acquire it itself through the current HttpContext.

protected void Session_End(object sender, EventArgs e)
{
// HttpContext.Current.Session throws a
// NullReferenceException since no HttpContext
// exists when a session expires, thus the client
// code can't access the HttpSessionState object this
// way and needs it to be passed directly from
// Global.asax (i.e. this.Session)

this.Controller.Cleanup(this.Session);
}

No comments: