1.06.2011

Using NHibernate with Windows Communication Foundation (WCF)

Our team recently wanted to use WCF to create a new web service. We are using nHibernate as our ORM. We used a pattern described by Jeffery Palermo to integrate NHibernate into our MVC applications and were interested in doing something similar with WCF. Unfortunately, this method doesn’t work for WCF, at least not without the overhead of turning on AspNetCompatibilityRequirementsMode (just typing that hurts a little.) In my research, I discovered the IDispatchMessageInspector interface. This interface provides an AfterReceiveRequest and BeforeSendReply methods. This will allow me to open an NHibernate session before the message is processed and close it just before my reply is sent to the consumer. Additionally, because it is an interface, I can simply have my exisiting HttpModule implementation extend the IDispatchMessageInspector interface. My methods are implemented as follows:
public object AfterReceiveRequest(ref Message req, IClientChannel chan, InstanceContext context)
{
    context_BeginRequest(null, null);
    return null;
}
and
public void BeforeSendReply(ref Message reply, object correlationState)
{
    context_EndRequest(null, null);
}
This allows me to use the same code as my HttpModule. All that is left to do is tie the IDispatchMessageInspector to my service. We can do this by implementing the IServiceBehavior interface, we’ll call the class NHibernateWcfBehaviorExtension. I was lazy and did this on the same HttpModule class, multiple inheritance is awesome! The IServiceBehavior requires three methods, only one will actually do anything:
public void ApplyDispatchBehavior(ServiceDescription descriptoin, ServiceHostBase hostBase)
{
    foreach (ChannelDispatcher cd in hostBase.ChannelDispatchers)
    {
        foreach (EndpointDispatcher ed in cd.Endpoints)
        {
            ed.DispatchRuntime.MessageInspectors.Add(this);
        }
    }
}
This will load the message inspector on each of the service’s endpoints. Now all we need to do is tell WCF about this IServiceBehavior. This can be done by extending BehaviorExtensionElement. We’ll call our implementation NHibernateSessionStarter . This class should return the type and a new instance of NHibernateWcfBehaviorExtension. Once we have the BehaviorExtensionElement, we can use it to tell WCF about our IServiceBehavior in the Web.Config.
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <!-- Service behavior is added here. -->
        <NHibernateSessionStarter />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <extensions>
    <behaviorExtensions>
      <!-- Service behavior is defined here. -->
      <add name="NHibernateSessionStarter" type="Infrastructure.NHibernateWcfBehaviorExtension, Infrastructure, Version=1.0.0.0, Culture=neutral" />
    </behaviorExtensions>
  </extensions>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Voila, WCF configured to use the same NHibernate startup and cleanup as our MVC apps.

5 comments:

  1. If you use SQL and stored proc that then gets mapped by nHibernate and exposed via WCF which is then consumed by a MVC App which then needs nHibernate to map and you now have a data-layer.

    Is there an advantage to this? Or did it just get lost with all the overhead?

    I'm trying to get up to speed with WCF and wrap a good understanding of Nhibernate and best practices here. So given that the flavor of the month is MVC, nHibernate and WCF, I'm just trying to figure out a "best practices" to wrap my self around here.

    ReplyDelete
  2. @CIBYG

    There definitely is some performance overhead.

    The stored proc that I am using in another post is a legacy stored proc, I don't have a choice about using it. I don't like stored procs and stay away from them at all costs.

    The WCF service is consumed by a legacy application written in ColdFusion, again no choice but to support it. I am trying to wean these applications from hitting my database directly.

    If I can get all of the legacy apps out of the database, then I can get rid of the stored procedures. That leaves me with database -> NHibernate -> business layer. I can expose the business layer in whatever format I want, MVC, WCF, POX, or whatever three letter acronym is popular at the moment. All of it relying on the same data persistence code.

    ReplyDelete
  3. Hello Scott
    this is exactly i am looking for .. I have a working app with Nhibernate.. Now i want it to wrap in a WCF and use it in my new (POC) MVC app..


    Could you please share a sample working example here. this wold be very helpful.

    Thanks in advance

    ReplyDelete
  4. Scott - Great article. One question - where/how are you bootstrapping up NHibernate (when it parses your xml mapping files and such)?

    ReplyDelete
  5. @Drew, sorry for the delay in responding. I've been on vacation. Anyway, if you take a look at the Palermo article, you'll see that he recommends implementing IHttpModule. I do the same on the class I show a part of here. Actually, my class is the same as Palermo's, except it also implements the IDispatchMessageInspector.

    I would post some sample code, but I am on a different project right now (different company actually) and don't have access to the source anymore, and unfortunately don't have any time to reconstruct it.

    ReplyDelete