5
votes

I have a number of WCF services setup which are consumed by angularjs. Currently I've run into a problem that I'm struggling with. I keep receiving the following error message when calling the WCF services. Any pointers on how to fix the issue would be appreciated. A more detailed error message can be found at the bottom

Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

Edit: It seems to work when I build the container in global.asax Application_BeginReques() also, hence not only Application_Start. No clue why but at least this is better than before.... However I've previously had this error occur every now and then so I don’t trust this ugly work-around

Here is my global.asax

        ..
        ..

    protected void Application_Start(object sender, EventArgs e)
    {
        var containerBuilder = new IoC();

        // Register your service implementations.
        containerBuilder.Builder.RegisterType<Konstrukt.SL.Services.GetBudgetData>().Named<object>("GetBudgetDataService");
        containerBuilder.Builder.RegisterType<Konstrukt.SL.Services.GetReferenceData>().Named<object>("GetReferenceDataService");
        containerBuilder.Builder.RegisterType<Konstrukt.SL.Services.UpdateBudgetData>().Named<object>("UpdateBudgetDataService");
        ..
        ..
        containerBuilder.Builder.RegisterType<Konstrukt.SL.Services.DimValue>().Named<object>("DimValueService");
        containerBuilder.Builder.RegisterType<Konstrukt.SL.Services.DisplayNameMapping>().Named<object>("DisplayNameMappingService");
        ..
        ..

        // use only one context object per scope/request
        containerBuilder.Builder.RegisterType<Konstrukt.DAL.KonstruktEntities>().InstancePerLifetimeScope();

        AutofacHostFactory.Container = containerBuilder.Builder.Build();
    }

Here is my IoC class which registeres all the interfaces

public class IoC
{
    private ContainerBuilder _builder;
    public ContainerBuilder Builder 
    {
        get 
        {
            if (_builder == null)
            {
                _builder = new ContainerBuilder();

                _builder.RegisterType<BL.App.App>().As<BL.App.IApp>();
                _builder.RegisterType<BL.AppConfig.AppConfig>().As<BL.AppConfig.IAppConfig>();
                _builder.RegisterType<BL.AppConfig.ComponentSetting>().As<BL.AppConfig.IComponentSetting>();
                _builder.RegisterType<BL.AppConfig.Component>().As<BL.AppConfig.IComponent>();
                _builder.RegisterType<BL.AppConfig.AppSetting>().As<BL.AppConfig.IAppSetting>();
                _builder.RegisterType<BL.AppConfig.AppDataSet>().As<BL.AppConfig.IAppDataSet>();
                _builder.RegisterType<BL.AppConfig.AttributeData>().As<BL.AppConfig.IAttributeData>();
                _builder.RegisterType<BL.AppConfig.Constants>().As<BL.AppConfig.IConstants>();
                ..
                ..
                _builder.RegisterType<BL.DimensionData.DisplayNameMapping>().As<BL.DimensionData.IDisplayNameMapping>();
                ..
                ..
                //DAL registrations, etc
                ..
                ..

            }
            return _builder;
        }
        set { _builder = value; }
    }

}

Sample WCF service implementation

public class DimValue : IDimValue
{
    private BL.DimensionData.IDimValue _dimValue;
    public DimValue(ILifetimeScope container, BL.DimensionData.IDimValue dimValue)
    {
        AutofacHostFactory.Container = container;
        _dimValue = dimValue;
    }

    public IList<Shared.Poco.DimValue> GetDimValueList(int budgetId, string dimensionFilterJSON, string userId)
    {
        Dictionary<Shared.Poco.Dimension, List<string>> dimensionFilters = null;
        Shared.Poco.User user = new Shared.Poco.User { UserId = userId };
        IList<Shared.Poco.DimValue> list = new List<Shared.Poco.DimValue>();

        using (var scope = AutofacHostFactory.Container.BeginLifetimeScope())
        {
            dimensionFilters = JsonConvert.DeserializeObject<Dictionary<Shared.Poco.Dimension, List<string>>>(dimensionFilterJSON);

            foreach (KeyValuePair<Shared.Poco.Dimension, List<string>> kvp in dimensionFilters)
            {
                foreach (Shared.Poco.DimValue dv in _dimValue.GetDimValueList(budgetId, kvp.Key, kvp.Value, user))
                {
                    list.Add(dv);
                }
            }
        }
        return list;
    }
}

[ServiceContract]
    public interface IDimValue
    {
        [OperationContract]
        [WebInvoke(Method = "GET",
                    RequestFormat = WebMessageFormat.Json,
                    ResponseFormat = WebMessageFormat.Json,
                    BodyStyle = WebMessageBodyStyle.Bare,
                    UriTemplate = "GetDimValueList?budgetId={budgetId}&dimensionFilterJSON={dimensionFilterJSON}&userId={userId}")]
        IList<Shared.Poco.DimValue> GetDimValueList(int budgetId, string dimensionFilterJSON, string userId);
    }

service markup

<%@ ServiceHost Language="C#" 
Debug="true" 
Service="DimValueService"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf" 
CodeBehind="DimValue.svc.cs" %>

Detailed error when calling DimValue.svc/GetDimValueList

The server encountered an error processing the request. The exception message is 'Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.'. See server logs for more details. The exception stack trace is: at Autofac.Core.Lifetime.LifetimeScope.CheckNotDisposed() at Autofac.Core.Lifetime.LifetimeScope.BeginLifetimeScope(Object tag) at Autofac.Core.Lifetime.LifetimeScope.BeginLifetimeScope() at Autofac.Integration.Wcf.AutofacInstanceContext..ctor(ILifetimeScope container) at Autofac.Integration.Wcf.AutofacInstanceProvider.GetInstance(InstanceContext instanceContext, Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance(InstanceContext instanceContext, Message request) at System.ServiceModel.InstanceContext.GetServiceInstance(Message message) at System.ServiceModel.Dispatcher.InstanceBehavior.EnsureServiceInstance(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

1

1 Answers

5
votes

The problem is that your service implementation is taking in a child lifetime scope and then changing the global lifetime scope.

The ILifetimeScope coming into your service implementation is a child of the container specific to that insurance of the service implementation and it gets disposed when the service implementation gets disposed.

But the service implementation is switching the global container - AutofacHostFactory.Container - to be that child lifetime scope. So when the service instance goes away... So does, now, the global container.

Stop setting the container from the service and you should be fine.

In general, after app startup, you really shouldn't be messing with the global root container.