Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve Autofac InstancePerHttpRequest

I have registered a component like this in my Global.asax.cs:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());

builder.RegisterType<WebWorkContext>().As<IWorkContext>().InstancePerHttpRequest();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

// This is where my error happens, not sure why?
var workContext = container.Resolve<IWorkContext>();

WebWorkContext class:

public class WebWorkContext : IWorkContext
{
     // Left out other code
}

IWorkContext interface:

public interface IWorkContext
{
     // Left out other code
}

The error that I am getting is:

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.

How do I get this to work? This reason why I want it this way is because the work context handles stuff like getting the current customer etc.

Some more questions. Is it wise/best practices to register every at once? Will the be scenarios that I will need to add more components at another stage?

like image 215
Brendan Vogt Avatar asked Apr 05 '12 11:04

Brendan Vogt


People also ask

What is resolve in Autofac?

After you have your components registered with appropriate services exposed, you can resolve services from the built container and child lifetime scopes. You do this using the Resolve() method: var builder = new ContainerBuilder(); builder. RegisterType<MyComponent>(). As<IService>(); var container = builder.

How do I get Autofac containers?

From Visual Studio, you can get it via NuGet. The package name is Autofac. Alternatively, the NuGet package can be downloaded from the GitHub repository (https://github.com/autofac/Autofac/releases).

What is InstancePerLifetimeScope?

InstancePerLifetimeScope means a new instance of the service will be created for every lifetime scope which asks for your service. Each web request gets its own fresh lifetime scope, so in practice, more often than not, these two will do the exact same thing.

What is ILifetimeScope?

An ILifetimeScope tracks the instantiation of component instances. It defines a boundary in which instances are shared and configured. Disposing an ILifetimeScope will dispose the components that were resolved through it. Namespace: Autofac.


1 Answers

Registrations that are marked with InstancePerHttpRequest are expected to be resolved from a particular nested lifetime scope that is created and disposed during each HTTP request.

If you add IWorkContext as a constructor parameter to one of your controllers you will find that an instance is injected. In your code you are attempting to resolve your service from the root lifetime scope and not the nested "per request" lifetime scope.

If you want to test resolving the service without running up your application you will need to create a lifetime scope with the same tag as the one created during the HTTP request. In the MVC 3 integration the lifetime scope is tagged "httpRequest".

using (var httpRequestScope = container.BeginLifetimeScope("httpRequest"))
{
    Assert.That(httpRequestScope.Resolve<IWorkContext>(), Is.Not.Null);
}

I think I will update the MVC integration to expose the "httpRequest" tag name publicly through the API so that string values don't need to be hard coded. It is also possible to pass your own ILifetimeScopeProvider implementation to the AutofacDependencyResolver so that you can control the creation of lifetime scopes outside of the ASP.NET runtime. This is useful in unit tests when there is no HTTP request available.

like image 59
Alex Meyer-Gleaves Avatar answered Sep 20 '22 13:09

Alex Meyer-Gleaves