Monday, February 16, 2009

WCF / Windsor Integration: Using the perWebRequest lifestyle

I briefly introduced Windsor WCF Integration a while back. I've been using it successfully in one of my current projects, but we had an issue recently with enabling the 'perWebRequest' lifestyle. Our project also uses the Windsor NHibernate Facility which automatically provides 'session per request' that we wanted to reuse with our WCF services. Both require a reference to the current HttpContext, but by default WCF does not integrate with the ASP.NET pipeline. This is by design, because it is intended that you should be able to host your WCF service with diverse protocols/hosts, not just HTTP/IIS/ASP.NET. But if you are simply using WCF to host services alongside an existing ASP.NET application and you want to reuse the same Windsor configuration for both it would be useful if WCF could gain access to the ASP.NET pipeline.

And voila! There is indeed a way of configuring WCF to integrate, simply set the serviceHostingEnvironment aspNetCompatibilityEnabled property to 'true' like this:

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  </system.serviceModel>

You also need attribute your service class to require/allow integration:

[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class MyService : IMyContract
{
    ....
}

Now HttpContext.Current returns the current HttpContext as expected and both the 'perWebRequest' lifestyle and the NHibernate Facility work as expected. It also means that your service can participate in your application's security settings, session state and impersonation if that's what floats your boat. Of course it doesn't help you if you want to host your service outside of IIS. In that case you'd probably want to either implement your own custom lifestyle that works with the OperationContext (WCF's equivalent to HttpContext) or implement an IEndpointBehavior. There's an example of how to do the latter in the WCF Facility's unit tests. Check out the UnitOfworkEndPointBehavior class.

More detail on the ASP.NET compatibility settings can be found in this excellent blog post by Wenlong Dong.

7 comments:

M@t said...

Mike, does this only apply if the binding from the client to the WAS hosted service is http?

Would it work, for example, if I was using nt.tcp binding?

Mike Hadlow said...

M@t,

It only works when your hosting the WCF service as part of an ASP.NET application on IIS over HTTP.

Sebastien Lambla said...

There's WCF OperationContext that does the same thing on the OpContext side of things if you want to host out of asp.net

Andreas Öhlund said...

I've created a similar solution to what Sebastien suggests for StructureMap that might give some ideas on how create a hosting agnostic solution:

http://andreasohlund.blogspot.com/2009/04/unitofwork-in-wcf-using-structuremap.html

Mike Hadlow said...

Thanks Andreas, nice work. I'll try and work up a similar example for Windsor.

Krlos said...

Why don't u use windsor transient property for the service?

Restuta said...

Thank you very much, it was a real pain until I've found your post.