I am having a Web API application in which the controller has Services/Repositories etc. injected into it through Dependency Injection (Unity). Let's assume that I have an IStuffService
that needs the IPrincipal
of the current request (or a wrapper around it).
The problem with Web API seems to be that the only reliable source of the current Request/User is the Request
property on the instance of the ApiController
. Anything static (be it HttpContext.Current
, CallContext.Get/SetData
or Thread.Get/SetData
) is not guaranteed to be on the same thread due to the sync nature of Web API.
How do I reliably ensure that Request-specific context is passed through dependencies, and more importantly, that the operation retains the correct IPrincipal
all the way through the operation?
Two options:
IPrincipal
has it as an argument to the method - that is the most reliable way, but it also requires me to have that thing in every method signaturecontainer.Resolve(opType, new DependencyOverride(typeof(IPrincipal), principal))
Option 2 means that my method signatures are clean, but it also means I need to make sure all dependencies are using the TransientLifetimeManager, not a Singleton or even Per-Thread one.
Is there a better solution than I'm not seeing?
“ - In software development, dependency injection is a technique where one object supplies the needs, or dependencies, of another object.
What is Dependency Injection: Dependency Injection is the main functionality provided by Spring IOC(Inversion of Control). The Spring-Core module is responsible for injecting dependencies through either Constructor or Setter methods.
Constructor injection should be the main way that you do dependency injection. It's simple: A class needs something and thus asks for it before it can even be constructed. By using the guard pattern, you can use the class with confidence, knowing that the field variable storing that dependency will be a valid instance.
ASP.NET Core injects objects of dependency classes through constructor or method by using built-in IoC container. The built-in container is represented by IServiceProvider implementation that supports constructor injection by default. The types (classes) managed by built-in IoC container are called services.
From the comments:
@MichaelStum, I believe HttpContext.User should be flowed correctly across async/await (within the same HTTP request). Is it not for you? – Noseratio 17 hours ago
@Noseratio See the other answers - in .net 4.0, it's bound to the current thread and was not properly maintained. It seems that in 4.5, this might be fixed. That said, HttpContext.Current is still not that appropriate in Web API because on self-hosted ones there is no HttpContext.Current.
AFAIK, there's no proper support for async/await
in ASP.NET 4.0 anyway (you probably can use Microsoft.Bcl.Async
for the language support, but there is no ASP.NET runtime support, so you'd have to resort to AsyncManager
to implement the TAP pattern).
That said, I'm 99% sure Thread.CurrentPrincipal
would still be correctly flowed across await
continuations in ASP.NET 4.0. That's because it gets flowed as a part of ExecutionContext
flow, rather than by synchronization context. As to HtttContext.Current.User
, I'm not sure if it would flow correctly in ASP.NET 4.0 (although it certainly does in ASP.NET 4.5).
I've re-read your question, but could find an explicit complaint about Thread.CurrentPrincipal
not being correctly flowed. Are you experiencing this issue in existing code (if so, it probably would be a bug in ASP.NET)?
Here's a list of related questions, answered with some great insights by Stephen Cleary:
Understanding context in C# 5 async/await
Why is an "await Task.Yield()" required for Thread.CurrentPrincipal to flow correctly?
Using ASP.NET Web API, my ExecutionContext isn't flowing in async actions
This blog post by Scott Hanselman is also related, although he speaks about WebForms:
If you're concerned about self-hosting scenarios, I believe Thread.CurrentPrincipal
will still be flowed correctly there (once having been set to a correct identity). If you want to flow any other properties (besides those which get automatically flowed with ExecutionContext
), you can roll out your own synchronization context. Another option (not so nice, IMO) is to use custom awaiters.
Finally, if you face a situation where you actually require thread affinity across await
continuation (much like in a client side UI app), you have such option, too (again, using a custom synchronization context):
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With