1.20.2011

Application Can't Find References

For the past several hours I have been trying to understand why a C# console application would not build. I'm using Visual Studio 2010. I have several other console applications that are working properly. However, this one kept claiming that it could not find two custom assemblies that I had referenced. I was getting
The type or namespace name 'StructureMap' could not be found (are you missing a using directive or an assembly reference?)
Of course, I checked repeatedly that the assemblies were in fact referenced. I even went as far as deleting and recreating the project, all to no avail. I finally found a stackoverflow post that addressed the problem. Turns out my custom assemblies are compiled targeting the .NET 4 Framework. My console application was only targeting the .NET 4 Client Profile. This caused the console application to lose track of the custom assemblies. Extremely frustrating as the error message was not indicative of the problem. Glad it was an easy fix though.

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.