Easy way to startup NHibernate in a WCF project
I'd like to use an NHibernate startup module for my WCF project like the one I use for my ASP.NET MVC projects. Jeffery Palermo 开发者_开发百科outlines the startup module that I use in his post ASP.NET MVC HttpModule Registration. Essentially the code boils down to adding a startup module in the web.config that looks like this:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="StartupModule" type="Infrastructure.NHibernateModule, Infrastructure, Version=1.0.0.0, Culture=neutral" />
</modules>
</system.webServer>
This is not working when I try to run the service with the WCF Test Client or directly against the endpoint with SoapUI. What are my options for a simple startup mechanism for NHibernate in a WCF project?
You can resolve the issue by using a Message Inspector. On your NHibernateModule implement IDispatchMessageInspector. This will allow you to open your NHibernate session as each request is received and close it right before your reply is sent out.
Palermo's demo indicates that you will have extended IHttpModule. If that is the case, you will add two methods for the IDispatchMessageInspector interface:
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
context_BeginRequest(null, null);
return null;
}
and
public void BeforeSendReply(ref Message reply, object correlationState)
{
context_EndRequest(null, null);
}
This will implement the new interface using your old code. You will also need to implement the IServiceBehavior interface. This will allow you to use the module on a behavior extension in your web.config. The IServiceBehavior requires three methods, only one will actually do anything:
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.MessageInspectors.Add(this);
}
}
}
This will add your new inspector to each of the endpoints.
You will then have to add a BehaviorExtensionElement. This BehaviorExtensionElement should return the type and a new instance of your NHibernateModule. This will allow you to create a new behavior that returns the NHibernateModule in your web.config.
public class NHibernateWcfBehaviorExtension : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(NHibernateModule); }
}
protected override object CreateBehavior()
{
return new NHibernateModule();
}
}
Now you have all the pieces in order, you can use them in your web.config. To apply them to all services your web.config should look like the following.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<NHibernateSessionStarter />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="NHibernateSessionStarter" type="Infrastructure.NHibernateWcfBehaviorExtension, Infrastructure, Version=1.0.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
精彩评论