Autofac WCF not injecting

2,728 views
Skip to first unread message

Tomek Pluskiewicz

unread,
Sep 14, 2011, 6:17:46 AM9/14/11
to aut...@googlegroups.com
Hi

I'm having hard time getting WCF Integration to work. It seems that I've done everything right accoring to Autofac wiki. The problem is that my service doesn't get created with the right constructor but with the parameterless instead. If I remove the parameterless constructor, WCF complains.

Having delved into the implementation, it seems that AutofacInstanceProvider#GetInstance method is never called. I presume it is where proper resolving from the container should take place...

Below is my config:

<system.serviceModel>
    <serviceBehaviors>
        <behavior name="defaultBehavior">
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <serviceMetadata httpGetEnabled="true"/>
        </behavior>
    </serviceBehaviors>
    <services>
    <service behaviorConfiguration="defaultBehavior" name="ITeam.Srk.Business.Services.ContractSalesWcfService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="clearHttpBinding" bindingNamespace="namespace" contract="ITeam.Srk.Business.Contract.IContractSalesWcfService"/>
    </service>
    <basicHttpBinding>
        <binding name="clearHttpBinding">
            <security mode="None" />
        </binding>
        <binding name="secureHttpBinding">
            <security mode="TransportWithMessageCredential">
                <message clientCredentialType="UserName" />
            </security>
        </binding>
        <binding name="largeMessageHttpBinding" maxBufferSize="10000000"
            maxReceivedMessageSize="10000000" messageEncoding="Text" transferMode="Buffered">
            <readerQuotas maxArrayLength="10000000" />
            <security mode="None" />
        </binding>
    </basicHttpBinding>
</services>
</system.serviceModel>

And the svc file:
<%@ ServiceHost Language="C#" Debug="true" Service="ITeam.Srk.Business.Services.ContractSalesWcfService, ITeam.Srk.Business" Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf" %>

Please help

Regards,
Tomasz

Oleg Deribas

unread,
Sep 14, 2011, 6:37:52 AM9/14/11
to aut...@googlegroups.com

Hi,

 

You should not use Autofac.Integration.Wcf.AutofacServiceHostFactory directly in your .SVC file.

Create class inherited from AutofacServiceHostFactory, override CreateServiceHost(..) method where you should setup your Autofac container and register everything you need in WCF service’s constructor.

Then use this class as factory in .SVC file.

 

--

Oleg

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/ZDdsgryHDRUJ.
To post to this group, send email to aut...@googlegroups.com.
To unsubscribe from this group, send email to autofac+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/autofac?hl=en.

Tomek Pluskiewicz

unread,
Sep 14, 2011, 7:08:26 AM9/14/11
to aut...@googlegroups.com
That is not what the wiki says ;).

Also I think you are wrong by suggesting to configure the container inside AutofacServiceHostFactory... It's simply not the right place. Or is it?

Regards
Tomasz

Oleg Deribas

unread,
Sep 14, 2011, 8:51:17 AM9/14/11
to aut...@googlegroups.com

Hi,

 

Wiki says that here: http://code.google.com/p/autofac/wiki/WcfIntegration#WAS_Hosting_and_non-HTTP_Activation

And this method works for any type of WCF service (both HTTP and non-HTTP bindings).

 

--

Oleg

--

You received this message because you are subscribed to the Google Groups "Autofac" group.

To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/hdLbnV2SkPMJ.

Tomek Pluskiewicz

unread,
Sep 14, 2011, 10:31:49 AM9/14/11
to aut...@googlegroups.com
Oh I found the problem. The service was marked as InstanceContextMode.Single. Changing to PerCall resolved one problem but leads to another.

Not I'm getting an exception saying:
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.

Now if I set AutofacHostFactory.Container to IContainerProvider.RequestLifetime, the call to container.BeginLifetimeScope() throws an exception saying it's already been disposed.

 What is the correct way to handle service with perhttprequest dependency?

Alex Meyer-Gleaves

unread,
Sep 14, 2011, 11:25:13 AM9/14/11
to aut...@googlegroups.com
Hi Tomek,

It sounds like your service is registered as SingleInstance but its dependency is registered as InstancePerLifetimeScope. If you register the service as InstancePerLifetimeScope you will not have this problem. 

Given that you had the InstanceContextMode set to Single it sounds like you wanted a singleton WCF service. This is usually not a good idea from a scalability point of view, and if you allow multiple callers to access that one instance using ConcurrencyMode.Multiple you will also need to be careful about multiple threads accessing any shared state.

The issue with the InstanceContextMode being set to Single is that WCF will attempt to create a singleton instance for you in the constrcutor of the ServiceHost instance that is created by the base ServiceHostFactory. When that instance is created it uses the default constructor and does not give Autofac (or anything else for that matter) a chance to get involved in the creation of the service instance. This is the reason for you getting the exception when you removed the default constructor.

This essentially means that the WCF integration does not support constructor injection with IIS hosting when InstanceContextMode.Single is used.

It is possible to do this when self-hosting by resolving a SingleInstance service from the container and then passing that into the constructor of the manually created ServiceHost. For example:

// Get your SingleInstance from the container.
IEchoService echoService = container.Resolve<IEchoService>(); 
Uri address = new Uri("http://localhost:8080/EchoService"); 
// Pass it into the ServiceHost preventing it from creating an instance with the default constructor.
ServiceHost host = new ServiceHost(echoService, address); 

I would go with a PerCall service if there is no reason preventing you from doing so. I will also make a note on the wiki about this limitation.

Cheers,

Alex.

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/Au8BHN-fIBcJ.

Tomek Pluskiewicz

unread,
Sep 15, 2011, 4:13:13 AM9/15/11
to aut...@googlegroups.com
Hi

Thank you for your input.

I've changed the service to PerCall. Singleton was not my idea so I didn't notice at first. And I don't approve as well.

Still I can't figure out how to get it working. Assigning AutofacHostFactory.Container = builder.Build() doesn't work and results in lifestyle mismatch as earlier.

I tried doing AutofacHostFactory.Container = ContainerProvider.RequestLifetime instead but this causes an exception on container.BeginLifetimeScope() saying "Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.";

I'm not sure what is the question I should ask. Is there a way to make BeginLifetimeScope return a scope for httpLifestyle? Or am I missing something else?

Regards
Tomasz

Alex Meyer-Gleaves

unread,
Sep 15, 2011, 7:59:15 AM9/15/11
to aut...@googlegroups.com
Hi Tomasz,

I think some more information is required. If you can post your container configuration code and the stack trace from the exception that might help. Also, what kind of application are you hosting the WCF service in (MVC, WebApp, Website)?

Cheers,

Alex.

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/YDoenuQuiFUJ.

Tomek Pluskiewicz

unread,
Sep 19, 2011, 3:27:11 AM9/19/11
to aut...@googlegroups.com
Hi

We are hosting our service inside a WebApp. 

Container is configured like this:

public class WcfModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<ContractSalesWcfService>().InstancePerHttpRequest();
    }
}

builder.RegisterAssemblyTypes(typeof(ILoanContractService).Assembly)
    .Where(t => t.Name.EndsWith("Service"))
    .AsImplementedInterfaces()
    .InstancePerHttpRequest();

I have omitted anything else. ContractSalesWcfService depends on one service from the services assembly. And those work fine on their own (injected into Presenters of MVP pattern).

Here's our WCF config:

.svc file:

<%@ ServiceHost Language="C#" Debug="true" Service="ITeam.Srk.Business.Services.ContractSalesWcfService, ITeam.Srk.Business" Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf" %>

web.config:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="clearHttpBinding">
                <security mode="None" />
            </binding>
            <binding name="secureHttpBinding">
                <security mode="TransportWithMessageCredential">
                    <message clientCredentialType="UserName" />
                </security>
            </binding>
            <binding name="largeMessageHttpBinding" maxBufferSize="10000000"
                maxReceivedMessageSize="10000000" messageEncoding="Text" transferMode="Buffered">
                <readerQuotas maxArrayLength="10000000" />
                <security mode="None" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="defaultBehavior">
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <serviceMetadata httpGetEnabled="true"/>            
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service behaviorConfiguration="defaultBehavior" name="ITeam.Srk.Business.Services.ContractSalesWcfService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="clearHttpBinding" bindingNamespace="http://www.iteam.pl/srk/wcf/" contract="ITeam.Srk.Business.Contract.IContractSalesWcfService"/>
        </service>
    </services>
</system.serviceModel>

Finally here's the stack trace:

No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.

   w Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope)
   w Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable`1 parameters)
   w Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   w Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   w Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
   w Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   w Autofac.Integration.Wcf.AutofacInstanceContext.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) w D:\@Projekty\Autofac\src\Source\Autofac.Integration.Wcf\AutofacInstanceContext.cs:wiersz 103
   w Autofac.Integration.Wcf.AutofacInstanceProvider.GetInstance(InstanceContext instanceContext, Message message) w D:\@Projekty\Autofac\src\Source\Autofac.Integration.Wcf\AutofacInstanceProvider.cs:wiersz 80
   w System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance(InstanceContext instanceContext, Message request)
   w System.ServiceModel.InstanceContext.GetServiceInstance(Message message)
   w System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   w System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
   w System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
   w System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
   w System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
   w System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Thanks in advance

Travis Illig

unread,
Sep 19, 2011, 1:55:50 PM9/19/11
to Autofac
InstancePerHttpRequest only works for requests that run through the
ASP.NET request pipeline and use the ASP.NET request lifetime stuff in
Autofac.Integration.Web or Autofac.Integration.Mvc.

The WCF integration with Autofac (AutofacServiceHostFactory) doesn't
resolve things through the web integration, it uses the container you
set on the service factory (that "AutofacHostFactory.Container =
builder.Build()" line in the wiki).

Due to the difference in lifecycle between ASP.NET stuff (one instance
per HTTP request) and WCF (instance per call, single instance, etc.)
you can't really register dependencies for WCF services as
InstancePerHttpRequest.

Note: TECHNICALLY you could get this to work by doing some non-trivial
customizations to get a custom AutofacInstanceContext to name its
lifetime scope "httpRequest" but I wouldn't recommend it. It gets
pretty hairy pretty quick.

-T

Nicholas Blumhardt

unread,
Sep 20, 2011, 12:21:40 AM9/20/11
to aut...@googlegroups.com
Tomek,

Except in some rare circumstances, InstancePerLifetimeScope() is a portable alternative to InstancePerHttpRequest() etc. and can be used instead.

Cheers,
NB

--
You received this message because you are subscribed to the Google Groups "Autofac" group.

Tomek Pluskiewicz

unread,
Sep 20, 2011, 3:01:09 AM9/20/11
to aut...@googlegroups.com
I understand the InstancePerLifetimeScope() would apply as an alternative if I resolved the InstancePerHttpRequest() component first.

But in this case I am resolving the WCF service first and it than depends on something InstancePerHttpRequest().

I tried changing InstancePerLifetimeScope() to InstancePerDependency() but it still leads to the same exception saying that " No scope with a Tag matching 'httpRequest' is visible from the scope..."

What is the right way to do this?

Nicholas Blumhardt

unread,
Sep 20, 2011, 9:22:24 AM9/20/11
to aut...@googlegroups.com
Hi Tomek,

No - rather than having to resolve the InstancePerHttpRequest() component first, you need to change the InstancePerHttpRequest() component to InstancePerLifetimeScope(). This will make it resolvable both in ASP.NET and WCF.

Nick

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/1Yljmqq9LjcJ.

Tomek Pluskiewicz

unread,
Sep 20, 2011, 9:37:01 AM9/20/11
to aut...@googlegroups.com
Hi Nicholas

Ok, sound fine. So if I change the dependant component to InstancePerLifetimeScope() will it remain PerHttpRequest() in WebSite context?

Tomek

Nicholas Blumhardt

unread,
Sep 25, 2011, 11:36:31 AM9/25/11
to aut...@googlegroups.com
Hi Tomek,

Yes, that's correct.

Nick

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/-jpwb12ZdK0J.
Reply all
Reply to author
Forward
0 new messages