ASP.NET Developer. ALT.NET Supporter. Pragmatic Programmer. Published Writer.

Setting up ASP.NET MVC with Fluent NHibernate and StructureMap

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

Enjoyed this post? Share it with others!

  • DotNetKicks
  • DZone
  • Reddit
  • HackerNews
  • StumbleUpon
  • del.icio.us

26 Comments to Setting up ASP.NET MVC with Fluent NHibernate and StructureMap

  1. April 12, 2010 at 3:14 am | Permalink

    You could ofcourse have used my BoC project to save you some time ;-) :
    http://code.google.com/p/webdotnet/

    You’d just have to write a provider for StructureMap, which would take very little time (or use MS Unity, as that is the IoC container already supported)

  2. April 19, 2010 at 5:01 pm | Permalink

    Isn’t that code still leaking ISessions? I mean, the sessions are only being cleaned up at the end of the application but the cleanup should happen at the end of each request…

  3. Dsmacks's Gravatar Dsmacks
    May 3, 2010 at 1:09 pm | Permalink

    Nice article, any chance of some source code to download?

  4. Jefferson's Gravatar Jefferson
    May 16, 2010 at 6:15 am | Permalink

    Kevin, Great post. I’ve been looking for a more recent post about StructureMap. Many of the posts that I’ve found on the web are a few years old, and although are still applicable, many use the deprecated ForRequestedType. I’ve been trying to find some more recent posts as well that talks about some of the more advanced features of StructureMap. This one hit home for me and a project I’m developing at work.

    Thanks again,
    Jefferson

  5. May 16, 2010 at 12:04 pm | Permalink

    I got to a similar solution using Unity instead of StructureMap:

    http://letsfollowtheyellowbrickroad.blogspot.com/2010/05/nhibernate-sessions-in-aspnet-mvc.html

  6. June 3, 2010 at 2:50 am | Permalink

    I’ve wanted to move away from another IoC provider and migrate to StructMap for some time now. I thought I should let you know your well written yet simple to follow post convinced to make the change tonight.

    Thanks so much for documenting this Kevin!

  7. June 3, 2010 at 8:28 pm | Permalink

    Hi Kevin

    How to actually get the HttpContextScoped ISession in my controller?

  8. Mike's Gravatar Mike
    July 16, 2010 at 6:59 am | Permalink

    I like how you have this setup, except that I’m not injecting it into my controllers, I’m injecting it into my repository. And by the time the ISession gets to my repository, it’s closed. I don’t want to ahve to setup every controller to have an ISession that pass down to the repository.

    Thoughts?

  9. Mike's Gravatar Mike
    July 16, 2010 at 7:07 am | Permalink

    Well, nevermind. Just after i posted the comment i figured one piece out. I hvae my repository setup as a singleton in my mvc app by structuremap. so of course, when it comes around to the calling of a method, the injected ISession has been closed and disposed.

    ForSingletonOf().Use(x => x.GetInstance());
    .......
    private ISession Session;
    public CustomerRepository(ISession session) {
    Session = session;
    }
    public Customer GetCustomer(int CustomerNumber) {
    var customer = Session.Linq().FirstOrDefault(x => x.CustomerNumber == CustomerNumber);


    So How do i get the session back into the repository without having to put a parameter on each method? Or is that what needs to be done?

  10. Mike's Gravatar Mike
    July 16, 2010 at 7:09 am | Permalink

    it chopped the code:
    ForSingletonOf *CustomerRepository* ().Use *CustomerRepository* ();

    • Matt S.'s Gravatar Matt S.
      December 1, 2010 at 12:34 pm | Permalink

      @Mike: Either don’t scope your repositories, or scope them to the HttpContext. Then, their contructors will get the necessary ISession just fine. I see no reason to scope repositories as singletons.

  11. Robert's Gravatar Robert
    July 16, 2010 at 7:12 am | Permalink

    How have you set up unit tests for this system? If the data access layer has the NHibernate calls, but the session is created in the httpcontext, how do you create unit tests for the data access layer? I assume you would inject the session in the data access layer constructors, but it seems like you’d need to move the session creation out of the ObjectFactory.Initialize and put it in each TestSetup?

  12. Luka's Gravatar Luka
    September 9, 2010 at 2:03 am | Permalink

    Hi,
    I am constantly getting Session is closed error!

  13. Juan Francisco's Gravatar Juan Francisco
    September 11, 2010 at 1:16 pm | Permalink

    Hello, where do we should put the entry for “InsertConnectionString”?

  14. November 18, 2010 at 11:10 pm | Permalink

    Nice Post!

  15. Darshan's Gravatar Darshan
    November 26, 2010 at 12:14 am | Permalink

    Loved It! Saved my time!
    Thank you.

About

Kevin Pang is an ASP.NET developer and published writer with over 6 years of experience in the software industry.

Sponsors

Recent Tweets

  • @SaraJChipps StackOverflow has keyboard shortcuts? Is there a page that lists them out? 2 days ago
  • @shanselman I use keyboard shortcuts in gmail and reader. They're only useful on sites you visit frequently enough to bother learning them. 2 days ago
  • @jcroft 1 or 2 in general, but it's dependent on who my target audience is. 3 days ago
  • "Wide left". The two sweetest words in the English language. The Pats are going to the Super Bowl! 1 week ago
  • RIAA Reminds Us Why We Hate Them With Obnoxious Smartass Tweet http://t.co/SHhaijFC #fb 2 weeks ago