autofac / Autofac

An addictive .NET IoC container
https://autofac.org
MIT License
4.5k stars 837 forks source link

Can not resolve the lifetimescope type in Application_EndRequest with Mvc 5 integration #570

Closed liuhongbo closed 10 years ago

liuhongbo commented 10 years ago

This happen after upgrade to v3.3.3

It will throw an exception

Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.
tillig commented 10 years ago

The request lifetime itself is disposed in the EndRequest event. You can see this in the RequestLifetimeHttpModule which gets added automatically to your pipeline when you reference the MVC integration. Most likely there is a race condition where the Autofac event handler is firing before your own EndRequest event handler. This is most likely cropping up now simply because more recent Autofac integration tries to make the registration of the module, etc. more seamless to the developer so we register the module on pre-application-start. We subscribe to the event first, so we get called first.

Unfortunately, there's really not much to be done about it from the Autofac side - EndRequest is the last event in the pipeline and we have to dispose of the lifetime scope, so that's where it happens.

If you are handling something at EndRequest that needs to be resolved, it may be too late. Even in previous integrations, EndRequest would have been a risk. For example, if you resolve an object that implements IDisposable, the release of the lifetime scope on EndRequest would dispose of the object and you'd be working with an object in a bad state.

I recommend trying to move the execution of your action to some time before EndRequest. Alternatively, if you are 100% sure that the objects in your chain aren't IDisposable, you could resolve the object in an earlier event, store it in HttpContext.Items, and retrieve it from there to use in your EndRequest handler.

kiwidev commented 9 years ago

I just came across this with Owin integration. The completion of Owin Middleware pipeline pieces (such as Katana Authentication) is triggered by the EndRequest event and so can run after the lifetime is disposed.

Since the Owin.UseAutofacMiddleware and UseAutofacMvc already take care of disposing the lifetime scope I've setup a custom ILifetimeScopeProvider which doesn't register the RequestLifetimeHttpModule.

Is this valid, and if so should it be automatically done by the Owin pieces?

tillig commented 9 years ago

Given...

...we probably will not be changing the current OWIN integration story for MVC in this release. You will see a much different setup where a lot of this is avoided come ASP.NET 5.0, which is something we are actively working on right now.

If switching this up for your specific application satisfies a need for you, that's awesome, and I'm glad it works.

kiwidev commented 9 years ago

Cheers for the response and agree with the approach. Owin + MVC integration is an edge case at the moment, although possibly happening more often as some of the Katana libraries are pushed more.

Doing some more testing, switching the LifetimeScopeProvider does seem to work and solve my issue - thanks for making the library extensible in the right spots!

vincentparrett commented 8 years ago

I just hit this issue in my Application_Error handler, trying to show custom error pages with the correct response code. The worst part is I'm not trying to use the container directly, and have tried excluding my controller from registration - see http://stackoverflow.com/questions/36001166/mvc-5-custom-error-pages-when-using-autofac - so I'm between a rock and a hard place now.. I don't want to give up either autofac or custom error pages!

vincentparrett commented 8 years ago

BTW @kiwidev OWIN + MVC is not a corner case anymore, if you create a default mvc application in VS2015 it comes with all the owin startup code pre-wired.

vincentparrett commented 8 years ago

I just solved this by realising mvc was trying to resolve the modelbinder, but making my controller action methods parameterless stopped it from trying that.. problem solved.

DaleyKD commented 5 years ago

3 years later... what is the solution to using Autofac with a global exception handler in an MVC app?

PleasantD commented 3 years ago

It is stupid that this issue is close and still unresolved over 7 years after being reported. I ran into it myself today when I was unable to resolve services in the OWIN middleware after MVC had a chance to run.

First middleware is app.UseAutofacMiddleware(), which creates a new pre-request scope Second middleware is app.UseAutofacMvc(), which copies the lifetime scope into HttpContext.Current.Items[typeof(ILifetimeScope)]

Then my middleware Then MVC on top.

Imagine my shock to discover that for some reason when control returns to my middleware the lifetime scope in the OWIN context is disposed because an over-zealous RequestLifetimeHttpModule has disposed it.

My fix is to set HttpContext.Current.Items[typeof(ILifetimeScope)] equal to a nested scope created from the OWIN request scope.

So the proper autofac fix should be one of two things

  1. Have AutofacMvcAppBuilderExtensions.UseAutofacMvc set httpContextBase.Items[typeof(ILifetimeScope)] = autofacLifetimeScope.BeginLifetimeScope();
  2. OR have RequestLifetimeScopeProvider.EndLifetimeScope() not dispose a scope it did not create.
tillig commented 3 years ago

It is stupid that this issue is close and still unresolved over 7 years after being reported.

It might be beneficial to consider:

If you want to pursue a fix, I would recommend proposing something in the correct repo since this repo is core Autofac, not the MVC support. Include how you plan on making sure everything works in combination - one app that has:

If the fix breaks any of those other things, we can't take it. If the fix changes how things currently work in a way that would require folks to change code, we likely can't take it.

While I recognize this issue exists, if you do decide to pursue a new issue, please outline in the new issue the complete problem since, over time, the actual issue in context of all of the components with all the new versions and features is not necessarily clear. Please open the issue prior to submitting a PR.