How does "Require SSL" affect ASP.NET MVC application lifecycle?

1k views Asked by At

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.

2

There are 2 answers

1
David Pope On BEST ANSWER

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.

0
Oakcool On

Here is something that might help you

ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0

ASP.NET Application Life Cycle Overview for IIS 7.0

You might want to do what you are doing in global.asax instead.