Search code examples
asp.net-web-apidependency-injectionasync-awaitsimple-injector

When is the WebApiRequestLifestyle scope finished?


I am trying to get an instance from the container on an ActionFilter.OnActionExecuted. The dependency is registered with Lifestyle.Scoped in a web api. After debugging a problem, I can see that the instance returned in the filter is different than the one returned during the request (e.g. injected into controllers)

Can anyone please explain what exactly are the start and end of a webapirequest lifestyle scope?


Solution

  • The scope for WebApiRequestLifestyle is created at the moment that Web API calls IDependencyResolver.BeginScope() and it ends once it calls Dispose() on the returned IDependencyScope instance.

    In the past I noticed a few really weird quirks in Web APIs design that have to do with scoping and asynchonicity. For instance, Web API calls IDependencyScope.Dispose() after the async flow has already been finished. This means that at the time of the call to IDependencyScope.Dispose(), any data stored at the start of the request using CallContext.SetLogicalData can't be retrieved anymore at that point in time. So there is a gap between the end of the request and the disposal of the scope. Simple Injector depends on the availability of the CallContext during the request for resolving scoped instances.

    What might be happening is that Web API calls your OnActionExecuted during this gap. Only few developers ever notice this quirk, since usually, during the time of the gap, all dependencies are already resolved. If however you are resolving services during that stage, things go wrong in Web API.