Autofac WCF intergration does not handle request scope?

973 views
Skip to first unread message

Kendall Bennett

unread,
Nov 4, 2013, 8:41:34 PM11/4/13
to aut...@googlegroups.com
Hi Guys,

I am in the process of wrapping moving our code over to Autofac from Ninject (due to instability under high load in our web servers). The last thing I am stuck on is handling the WCF integration. It fails because when Autofac is trying to create my class, it tries to create it from the root scope, as that is the scope that is registered with the AutofacHostFactory.Container. Alas the service class we are using relies on tons of other classes that all need to be request scoped. Now in our case this is fine because the service runs under IIS, so every WCF request is handled within the context of a real web request.

So the catch is right now there is no way to have the Autofac WCF integration look for the service class in request scope, so of course it fails.

Got any suggestions on how to fix this? Clearly I can go back to using a service locator pattern in that class and grab what I need from request scope there, but it would be better if I can somehow signal to the Autofac WCF host factory to use request scope?

- Kendall

Alex Meyer-Gleaves

unread,
Nov 5, 2013, 8:42:35 AM11/5/13
to aut...@googlegroups.com
Hi Kendall,

The WCF integration creates services based on the operation lifetime. Because it needs to be host agnostic it does not deal specifically with web requests, but instead works with operation lifetimes through the AutofacInstanceContext.

If you have common dependencies between your WCF service and Web API or MVC controllers then mark those services as InstancePerLifetimeScope(). Your WCF services should also be marked as InstancePerLifetimeScope so that a new instance is provided for each operation lifetime.

I hope that gets you on the right track. Ping me back if that doesn't seem to be working for you.

Cheers,

Alex.

Kendall Bennett

unread,
Nov 30, 2013, 6:22:14 PM11/30/13
to aut...@googlegroups.com
Hi Alex,


On Tuesday, November 5, 2013 5:42:35 AM UTC-8, Alex Meyer-Gleaves wrote:
The WCF integration creates services based on the operation lifetime. Because it needs to be host agnostic it does not deal specifically with web requests, but instead works with operation lifetimes through the AutofacInstanceContext.

Right, but that can never be request scoped from what I can tell. It is always going to be scoped to the root scope, when in reality for WCF services hosted with in IIS, they need to be request scoped. There really needs to be a way to tell the Autoface WCF factory to use the current request scope for creating instances when running under IIS.
 
If you have common dependencies between your WCF service and Web API or MVC controllers then mark those services as InstancePerLifetimeScope(). Your WCF services should also be marked as InstancePerLifetimeScope so that a new instance is provided for each operation lifetime.

So you are saying that if you use InstancePerLifetimeScope() that every HttpRequest gets a separate scope, so therefore it would behave the same as InstancePerHttpRequest()? The catch is that the next piece of the puzzle is missing, in that there is no way to be able to get the Autofac WCF factory to use HttpRequest scope. It will always use the scope that was passed in to the AutofacHostFactory.Container instance, which will effectively act like a singleton instance across ALL WCF service class instances. So sure, you would end up with separate instances for the web requests and the WCF service requests, but ALL WCF service requests will end up getting the SAME instance from the factory, which clearly is not going to work.

Unless I am missing something and the Autofac WCF factory is going to create a new child scope for every WCF request that comes in, so each WCF request effectively would end up with separate instances of everything?

- Kendall

Kendall Bennett

unread,
Dec 1, 2013, 11:24:34 PM12/1/13
to aut...@googlegroups.com
I think I can answer my own question here:
As it turns out, after spending the afternoon debugging the Autofac WCF implementation, it does indeed create a new Lifetime scope for every instance that is served up, so basically every WCF service host instance gets all new dependencies for every service call, which mimics request scoping for ASP.NET web requests. So yes, in fact if I set all my service classes to use InstancePerLifetimeScope() then every WCF request and every HTTP request gets all new instances of all my classes that are marked that way.

Now that I understand how this works I plan to re-write my WCF code to use Autofac, but it dawned on me while implementing all of this that the use of the InstancePerHttpRequest() function which basically requires a scope with the tag named 'AutofacWebRequest' pretty much won't allow that code to be shared with anything in the WCF service stack. And in fact using InstancePerHttpRequest() is not even needed at all, because using InstancePerLifetimeScope() already ensures that every HTTP request gets separate instances anyway.

So now I am wondering why you would ever use InstancePerHttpRequest() for ASP.NET code? 

- Kendall

Alex Meyer-Gleaves

unread,
Dec 2, 2013, 7:17:38 AM12/2/13
to aut...@googlegroups.com
Hi Kendall,

Sorry for the late reply. I'm glad you got it sorted out.

Using InstancePerHttpRequest() is recommended for a web entry points such as MVC and Web API controllers, as well as supporting services such as model binders etc. It ensures that these components are created in the correct lifetime scope (HTTP request) and are not accidentally created more than once per request. It is possible to create a nested lifetime scope within a controller invocation and you generally don't want additional resolve operations to create duplicates of these services.

For services that you want to share between integrations it is perfectly fine to use InstancePerLifetimeScope() as you described. So I guess the rule is: use InstancePerHttpRequest() for services directly related to a per-request-based integration, and use InstancePerLifetimeScope() for services that are shared between them.

Cheers,

Alex.
Reply all
Reply to author
Forward
0 new messages