On a yet-to-be-released side project of mine, I decided to use Fluent NHibernate, StructureMap, and ASP.NET MVC. It took me awhile to get everything to play together nicely, so I documented the steps I took in case anyone out there was interested in using in a similar setup.
Step 1: Set up StructureMap
First, I created the StructureMapControllerFactory class (taken from the MvcContrib project):
public class StructureMapControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
try
{
var controllerType = base.GetControllerType(requestContext, controllerName);
return ObjectFactory.GetInstance(controllerType) as IController;
}
catch (Exception)
{
//Use the default logic
return base.CreateController(requestContext, controllerName);
}
}
}
Then, I added the following line to my Application_Start() function in Global.asax.cs so that StructureMap would inject dependencies for any ASP.NET MVC controller created:
protected void Application_Start()
{
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
Step 2: Set up Fluent NHibernate
Next, I created a static function for creating an ISessionFactory (this code may look very different depending on your database and project setup):
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(c => c.FromConnectionStringWithKey("InsertConnectionString")))
.Mappings(m =>
{
// Include both standard NHibernate mapping files and Fluent NHibernate mapping files
m.HbmMappings.AddFromAssemblyOf<User>();
m.FluentMappings.AddFromAssemblyOf<User>();
})
.BuildSessionFactory();
}
Step 3: Hook up Fluent NHibernate with StructureMap
Then, I updated my Application_Start() function in Global.asax.cs so that StructureMap would be aware of how to instantiate an NHibernate ISessionFactory and ISession:
protected void Application_Start()
{
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
ObjectFactory.Initialize(x =>
{
// ISessionFactory is expensive to initialize, so create it as a singleton.
x.For<ISessionFactory>()
.Singleton()
.Use(CreateSessionFactory());
// Cache each ISession per web request. Remember to dispose this!
x.For<ISession>()
.HttpContextScoped()
.Use(context => context.GetInstance<ISessionFactory>().OpenSession());
});
}
Now, whenever StructureMap needs to create an ISessionFactory, it calls the CreateSessionFactory() method defined in Step 2. Since ISessionFactory is expensive to create, I have configured StructureMap to create it as a Singleton so that it will only be created once per application.
Similarly, whenever StructureMap needs to create an ISession, it will create/retrieve an ISessionFactory instance and call its OpenSession() method. This is scoped at the HttpContext level, which means that at most, one ISession will be created by StructureMap per web request.
Step 4: Clean up
Finally, in order to ensure that we aren’t leaking ISessions on every web request, I added the following line to my Application_EndRequest function to properly dispose of the ISession StructureMap may have created during that web request:
protected void Application_EndRequest()
{
// Make sure to dispose of NHibernate session if created on this web request
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
The setup described above works on my machine with the following versions:
- ASP.NET MVC 2
- StructureMap 2.6.1
- Fluent NHibernate 1.0.0.594







