Subscribe to my feed here: http://feeds.jeffreypalermo.com/jeffreypalermo
Context
In many applications, I find the development team needs to have some bit of configuration code run at the very beginning, before any other code. In a web site on ASP.NET, we have the Global.asax file that has an Application_Start method. In an ASP.NET MVC app, we register routes and do other things before the first request is served by the application. One of the common start-up tasks my teams need to do is configuration NHibernate: setting up the configuration, creating the SessionFactory, etc. Because NHibernate is an infrastructure concern, one of our standards is that only the Infrastructure project has a reference to NHibernate.dll. This presents a special need on the UI project because the UI project is not allowed to reference the start-up code explicitly.
Solution
To get around this, we use an IHttpModule implementation to do start-up configuration. This module lives in the Infrastructure project off to the side, and we add it to the web.config file so that the ASP.NET runtime will call it. Here is a sample start-up module for NHibernate. Note that the only purpose is to catch a time before the first request, and you can slide in any start-up code:
public class NHibernateModule : IHttpModule
{
private static bool _startupComplete = false;
private static readonly object _locker = new object();
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
private void context_BeginRequest(object sender, EventArgs e)
{
EnsureStartup();
new DataConfig().StartSession();
}
private void context_EndRequest(object sender, EventArgs e)
{
new DataConfig().EndSession();
}
private void EnsureStartup()
{
if (!_startupComplete)
{
lock (_locker)
{
if (!_startupComplete)
{
new DataConfig().PerformStartup();
_startupComplete = true;
}
}
}
}
public void Dispose()
{
}
}
Explanation
We are using double-checked locking to ensure we only perform the start-up code once. This module is registered in the web.config here:
<configuration>
<system.web>
<httpModules>
<add name="StartupModule" type="Infrastructure.NHibernateModule, Infrastructure, Version=1.0.0.0, Culture=neutral"/>
</httpModules>
</system.web>
</configuration
This works fine if IIS7 is set to Classic mode. As soon we go to Integrated Mode, which is recommended on IIS7 for ASP.NET MVC, this module registration doesn’t work. Instead, we use the system.webServer node as shown below:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="StartupModule" type="Infrastructure.NHibernateModule, Infrastructure, Version=1.0.0.0, Culture=neutral"/>
</modules>
</system.webServer>
</configuration
There you have it. Works like a charm on IIS7 in Integrated Mode.