5

I have ASP.NET MVC application where I registered a component with an InstancePerHttpRequest scope.

builder.RegisterType<Adapter>().As<IAdapter>().InstancePerHttpRequest();

then I have an async piece of code where I'm resolving the Adapter component.

The following code is simplified

Task<HttpResponseMessage> t = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t =>

      // IHandleCommand<T> takes an IAdapter as contructor argument
      var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
);

The code above is throwing an exception: The request lifetime scope cannot be created because the HttpContext is not available.

So I did some research on the subject and found this answer https://stackoverflow.com/a/8663021/1003222

Then I adjusted the resolving code to this

 using (var c= AutofacDependencyResolver.Current.ApplicationContainer.BeginLifetimeScope(x => x.RegisterType<DataAccessAdapter>().As<IDataAccessAdapter>).InstancePerLifetimeScope()))
 {
       var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
 }

But the exception stayed the same. The request lifetime scope cannot be created because the HttpContext is not available.

Am I missing something ?

Community
  • 1
  • 1
user49126
  • 1,825
  • 7
  • 30
  • 53
  • Did you end up resolving this? I'm having the same issue after porting some code over from a previous (working) Web Api. In this solution Im using Web APi 2 and Autofac web api 2 integration I feel like the upgrade caused this. – parliament Feb 15 '14 at 19:44
  • @parliament the issue here is that HttpContext is MVC concept, but the request done via WebApi. ANd WebApi does not readily have access to HttpContext. And I presume one of the dependencies of the requested type is HttpContext. So Autofac can't resolve HttpContext, hance failing with exception. – trailmax Feb 15 '14 at 23:37

4 Answers4

4

you can try something like this:

using (var c= AutofacDependencyResolver.Current
                                       .ApplicationContainer
                                       .BeginLifetimeScope("AutofacWebRequest"))
{
   var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
}
KozhevnikovDmitry
  • 1,660
  • 12
  • 27
4

Autofac tries to resolve the container from the MVC Dependency Resolver, If you have a async operation the httpContext won't be available so DependencyResolver won't be available either.

One option in to make the container available in a static variable or a proper instance, and create a context scope for this operation.

public static IContainer Container

once you have the builder setup, copy the container

public class ContainerConfig
{
    public static IContainer Container;
    public static void RegisterComponents()
    {
        var builder = new ContainerBuilder();
        builder.RegisterInstance(new Svc()).As<ISvc>();
        Container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(Container ));
    }
}    

then when resolving use the static container config to create the instance you need.

using (var scope = ContainerConfig.Container.BeginLifetimeScope())
{
       result = ContainerConfig.Container.Resolve<T>();
}

hope it helps

Leo Hinojosa
  • 251
  • 2
  • 7
1

If you do not have access to System.Web.Http you can´t use DependencyResolver.Current. You need to store your container and Resolve the dependency from it:

//On Startup Class
public static IContainer Container { get; private set; }

public void Configuration(IAppBuilder app)
{
   ...
   var builder = new ContainerBuilder();
   builder.RegisterModule([yourmodules]);
   ...
   var container = builder.Build();
   Container = container;
}

Then, when you need your instance:

using (var scope = Container.BeginLifetimeScope())
{                                
   YourInterfaceImpl client = Container.Resolve<YourInterface>();
   ...
}

Hope this help!

Nacho
  • 21
  • 5
1

In my case I was instantiating all types on WebAPI startup, to catch any failures as early as possible. At that point, there's no request, so with a type registered as InstancePerRequest I was getting this error:

No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.`

Based on @KozhevnikovDmitry's answer, this is how I got it working:

using (var scope = container.BeginLifetimeScope("AutofacWebRequest"))
{
    foreach (Service item in container.ComponentRegistry.Registrations.SelectMany(x => x.Services))
    {
        Type type = item is TypedService ts ? ts.ServiceType
                  : item is KeyedService ks ? ks.ServiceType
                  : throw new Exception($"Unknown type `{item.Description}`");
        try
        {
            scope.Resolve(type);
        }
        catch (Exception ex)
        {
            _log.Debug($"Error instantiating type `{type.FullName}`", ex);
            throw;
        }
    }
}
demoncodemonkey
  • 11,730
  • 10
  • 61
  • 103