5
votes

I'm playing around with ASP.NET vNext and I'd like to utilize InstancePerRequest for some of my registrations, e.g MyDbContext would be one example.

I've got Autofac running using InstancePerLifetimeScope for these dependencies. Which works....

But as soon as I change over to use InstancePerRequest I get this common error:

DependencyResolutionException: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested 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.

I've read the Autofac help docs around this.... but I'm not sure how to set up the "request lifetime scope" which is causing this exception.

Has anyone set up an ASP.NET 5 web app integrating Autofac including InstancePerRequest?

1
I haven't try ASP.net v5 with Autofac yet but a common reason for this error is that HttpContext.Current is null while resolving. What is the stack trace of the exception ? are you resolving a type outside of a HTTP request ?Cyril Durand
Yeh at runtime it's trying to resolve the per request dependencies against a tagged lifetime scope which is what per request sits on top off. Problem is a lifetime scope hasn't been set yet. I'll put up the stack trace ASAP.Andrew Duffy

1 Answers

10
votes

You have two options as far as I know and both of them will give you the instance per request.

Assuming you have the below class to register:

public class Foo : IDisposable 
{
    public Foo()
    {
        Console.WriteLine("created");
    }

    public void Dispose()
    {
        Console.WriteLine("disposed");
    }
}

Register with IServiceCollection

You can register the instance as scoped on IServiceCollection and build the Autofac container based on this.

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddScoped<Foo, Foo>();

#if DNX451
            // Create the autofac container
            var builder = new ContainerBuilder();

            // Create the container and use the default application services as a fallback
            AutofacRegistration.Populate(builder, services);
            var container = builder.Build();

            return container.Resolve<IServiceProvider>();
#endif

            return services.BuildServiceProvider();
        }

Register on Autofac Builder

You can register the type on Autofac builder as instance per lifetime scope and this will give you the instance per request lifetime:

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
#if DNX451

            // Create the autofac container
            var builder = new ContainerBuilder();

            // Create the container and use the default application services as a fallback
            AutofacRegistration.Populate(builder, services);
            builder.RegisterType<Foo>().As<Foo>().InstancePerLifetimeScope();
            var container = builder.Build();

            return container.Resolve<IServiceProvider>();
#endif

            return services.BuildServiceProvider();
        }

As said, the result will be the same for both:

enter image description here

For more info per request instances on ASP.NET 5: Middlewares and Per Request Dependency Injection