I have an application that taps into BeginRequest
and EndRequest
to set up and tear down NHibernate sessions like this:
BeginRequest += delegate
{
CurrentSessionContext.Bind(SessionFactory.OpenSession());
};
EndRequest += delegate
{
var session = CurrentSessionContext.Unbind(SessionFactory);
session.Dispose();
Container.Release(session);
};
This works fine when deployed in IIS, until I check the "Require SSL" box. Once I do this, I get a NullReferenceException
at session.Dispose()
.
I haven't debugged this yet and, yes, the fix is trivial, but I'm just curious about how "Require SSL" affects the lifecycle of a request. Is a session not set up on the server in these cases?
EDIT: Just to clarify, I'm referring to the "Require SSL" option in IIS configuration for the application, not the RequireHttps
attribute for controllers.
This one piqued my curiosity so I dug into it a little; sorry for the necromancy.
I created a simple project that wired up notifications for every lifecycle event on the application object, and set breakpoints on each one.
It turns out that when "Require SSL" is set and you access without SSL, most of the events are completely skipped. The first event to fire is LogRequest
, followed by PostLogRequest
, EndRequest
, PreSendRequestContent
, and PreSendRequestHeaders
(in that order). No other events are fired.
So your code was crashing because the BeginRequest
event was never fired, and the EndRequest
delegate tried to Dispose()
something that had never been created.
What's interesting to me is figuring out why IIS behaves like this. I suspect the reason is that IIS still needs to log invalid connection attempts, as well as send content and headers, even if the requested resource requires SSL. Something has to generate that friendly "forbidden" page, after all. What I don't know is why EndRequest
is called at all when they didn't bother calling BeginRequest
; I'm guessing there's some IIS/ASP cleanup code that depends on it.
This behavior varies depending on whether the application pool is running in "Integrated" or "Classic" mode. In "Classic" mode, the ASP.NET events all fire "in between" the IIS PreRequestHandlerExecute
and PostRequestHandlerExecute
events. You didn't say which you were running, but it has to be Integrated; otherwise you'd have seen the behavior you were expecting, i.e. none of your code would have executed at all.
Interestingly, if you try to subscribe to the LogRequest
, PostLogRequest
, or MapRequestHandler
events when in Classic mode, you get a runtime exception; these only "make sense" in the context of the integrated pipeline.