I'm doing my final preparations today for speaking at VSLive San Francisco 2008 on Wednesday and Thursday. I went to check one of my demos and code that used to work started throwing an exception.
System.Web.HttpException was unhandled by user code
Message="Session state is not available in this context."
Source="System.Web"
ErrorCode=-2147467259
StackTrace:
at System.Web.HttpApplication.get_Session()
at UiDesignForTestability.WebUI.Global.InitializeMultiSessionFactoryNHibernate() in C:codebendaytfs2BDCbranchesUiDesignForTestabilityMultiDbUiDesignForTestability.WebUIGlobal.asax.cs:line 24
at UiDesignForTestability.WebUI.Global.Application_PreRequestHandlerExecute(Object sender, EventArgs e) in C:codebendaytfs2BDCbranchesUiDesignForTestabilityMultiDbUiDesignForTestability.WebUIGlobal.asax.cs:line 45
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
InnerException:
<ben:Panic operation="Start" intensity="Extreme" />
The offending code was trying to access the ASP.NET Session object from the PreRequestHandlerExecute event in my Global.asax.cs. This exception shouldn't be possible. In fact, it should be IMPOSSIBLE because according to the documentation, AquireRequestState should have fired already. (Can you tell that I was getting anxious? Getting on a plane tomorrow and the demos aren't working anymore. I fixed it but I'm still anxious anyway, actually.)
Ok. Well, it turns out that during Global.asax's processing, it fires all the events for each of the HttpHandlers in the pipeline. Well, not all HttpHandlers implement IRequiresSessionState. For example, System.Web.Handlers.AssemblyResourceLoader doesn't and that's what was causing the exception when InitializeMultiSessionFactoryNHibernate() was getting called.
protected void Session_Start(object sender, EventArgs e)
{
InitializeMultiSessionFactoryNHibernate();
}public void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
InitializeMultiSessionFactoryNHibernate();
}private void InitializeMultiSessionFactoryNHibernate()
{
if (Session["NHibernateConfiguration"] == null)
{
Session["NHibernateConfiguration"] = "UiDesignForTestability";
}SessionFacade.ConfigurationName = Session["NHibernateConfiguration"] as string;
}
Well, back on 5/30/2006 at 2:33am, Brock Allen wrote the solution into a comment here. The answer is to check that the current handler implements either IRequiresSessionState or IReadOnlySessionState.
public void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
InitializeMultiSessionFactoryNHibernate();
}
}
Thanks, Brock. This helped IMMENSELY.
Now the real question is why did that code work before?
-Ben