Autofac scope lifetime issue

2,680 views
Skip to first unread message

MartinF

unread,
Feb 25, 2013, 3:57:16 AM2/25/13
to aut...@googlegroups.com
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

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 ?

Alex Meyer-Gleaves

unread,
Feb 26, 2013, 8:09:16 PM2/26/13
to aut...@googlegroups.com
The code is calling DependencyResolver.Current which will attempt to get the request lifetime scope from the HttpContext.

Did you mean to resolve the handler out of the child lifetime scope that you created in the using statement?

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

MartinF

unread,
Feb 28, 2013, 5:48:52 PM2/28/13
to aut...@googlegroups.com
Didn't helped. The error is still the same.

MartinF

unread,
Mar 1, 2013, 3:43:09 AM3/1/13
to aut...@googlegroups.com
The error is thrown in the BeginLifetimeScope method.

Travis Illig

unread,
Mar 1, 2013, 12:30:39 PM3/1/13
to aut...@googlegroups.com
The call AutofacDependencyResolver.Current requires there be an HttpRequest scope present. To accommodate for tools like Glimpse which "wrap" or "proxy" the DependencyResolver, it's not just a standard "static reference" anymore.

So in the creation of that lifetime scope...

var c = AutofacDependencyResolver.Current.ApplicationContainer.BeginLifetimeScope...

You will get the exception because you're trying to get the current dependency resolver outside of a web request context during that continuation. It will be more obvious if you split that big line into something smaller and look at the stack trace:

.ContinueWith(t => {
  // You'll get the exception on this line:  
  var adr = AutofacDependencyResolver.Current;
  var container = adr.ApplicationContainer;
  using(var c = container.BeginLifetimeScope(...))
  {
    var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
  }
});

Off the top of my head I don't have any great foolproof suggestions (I'm a little behind on my "day job" as it were, so I can't mock something up and try stuff out).

Things I would try if I had the time:
  • See if you can create that lifetime scope OUTSIDE the ContinueWith call and make a closure over the scope. I don't think this will work because I think the scope will get disposed on one thread before the continuation happens, but it's worth a shot.
  • Hold your own static reference to the AutofacDependencyResolver somewhere in your app so you can use that instead of AutofacDependencyResolver.Current.
  • Use the Autofac.Extras.CommonServiceLocator integration and use the common service locator rather than the MVC/WebApi DependencyResolver from inside your non-web-context continuations. They can both share the same application container.
-T

Tim Schmidt

unread,
Jun 6, 2014, 9:20:23 AM6/6/14
to aut...@googlegroups.com
I just ran into into a similar problem.  Same error, slightly difference circumstances.  I unfortunately couldn't fix it in any of the ways suggested because I wasn't the one actually resolving the object out of the container.  In this case, the code (not mine) was rendering a Razor view in the controller but since there's an async operation in between, HttpContext.Current was null when the MVC guts tried to instantiate a view object.  I was able to fix it because I had access to the calling controller and was able to do this tremendous hack:

HttpContext.Current = controller.HttpContext.ApplicationInstance.Context;

Any chance of a better more permanent fix?

Kendall Bennett

unread,
Jun 6, 2014, 10:32:05 AM6/6/14
to <autofac@googlegroups.com>
I have completely stopped using per request scoping using named tags and instead always use InstancePerRequestScope(). If you register the classes that way they can resolve correctly for any scope and you can create sub-scopes for background work on a different thread and it gets different objects to the http request. Unless you have a really specific need for the request scope support this works a lot better for me and I can use the same registrations everywhere in our code.

So have you tried only using InstancePerRequestScope?

Regards,

Sent from my iPad Air!

Kendall Bennett, CEO
A Main Hobbies
424 Otterson Drive
Chico, CA 95928
--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To unsubscribe from this group and stop receiving emails from it, send an email to autofac+u...@googlegroups.com.
To post to this group, send email to aut...@googlegroups.com.
Visit this group at http://groups.google.com/group/autofac.
For more options, visit https://groups.google.com/d/optout.

Tim Schmidt

unread,
Jun 6, 2014, 12:12:14 PM6/6/14
to aut...@googlegroups.com
The problem is that I don't believe any registration or resolution trick would've helped since this was MVC resolving it's own class.

But as it turns out, we were killing ourselves here.  Since we had been using Glimpse which breaks some things in MVC 5, we had to add the "aspnet:UseTaskFriendlySynchronizationContext=false" flag to our web.config.  That was causing our HttpContext to go disappear when any async task resumed.  Getting rid of that setting has solved all of our problems!

Kendall Bennett

unread,
Jun 6, 2014, 4:21:25 PM6/6/14
to aut...@googlegroups.com
Interesting. I like Glimpse but ended up tossing it out as I never could get it to co-exist nicely with my classes. It has it's tentacles everywhere, and after chasing some nutty bugs that turned out to be Glimpse I took it out. Maybe I should look at that flag ...

Regards,

Kendall Bennett, CEO 
http://www.AMainHobbies.com
1-800-705-2215 (Toll-Free)
1-530-894-0797 (Local)

Facebook | Twitter | Youtube
Reply all
Reply to author
Forward
0 new messages