Closed liuhongbo closed 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.
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?
Given...
Dispose
multiple times on a container with no side effects (it'll only dispose once and ignore the future requests)...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.
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!
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!
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.
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.
3 years later... what is the solution to using Autofac with a global exception handler in an MVC app?
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
AutofacMvcAppBuilderExtensions.UseAutofacMvc
set httpContextBase.Items[typeof(ILifetimeScope)] = autofacLifetimeScope.BeginLifetimeScope();
RequestLifetimeScopeProvider.EndLifetimeScope()
not dispose a scope it did not create.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.
This happen after upgrade to v3.3.3
It will throw an exception