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:
Every method that needs an 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 signature
Inject the IPrincipal into the ctor of the Service, spinning up a new insance of the object graph on every request, using a DependencyOverride in Unity: container.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?
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:
System.Threading.Thread.CurrentPrincipal vs. System.Web.HttpContext.Current.User or why FormsAuthentication can be subtle
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):
How to use non-thread-safe async/await APIs and patterns with ASP.NET Web API?
The ultimate answer is that our IoC containers need to be changed to support async/await better.
Background:
The behavior of async/await around this changed between .NET 4 and .NET 4.5. In .NET 4.5 the SynchronizationContext was introduced and it will correctly restore HttpContext.Current (see http://msdn.microsoft.com/en-us/magazine/gg598924.aspx). However, it is often a best practice to use .ConfigureAwait(false) (see "Configure Context" in http://msdn.microsoft.com/en-us/magazine/jj991977.aspx) and that specifically requests that the context not be preserved. In that case you would still have the issue you describe.
Answer:
The best answer I have been able to come up with in my own code is to be sure to request the dependency that comes from HttpContext.Current (in your case IPrincipal) early in the web request so that is is loaded into the container.
I don't have any experience with Unity, but in Ninject this would look something like:
kernal.Bind<IPrincipal>().ToMethod(c => HttpContext.Current.User).InRequestScope();
Then I would be sure to load the IPrincipal early in the web request before you have lost the context. Either in BeginRequest or as a dependency of the controller. That will cause the IPrincipal to be loaded into the container for this request.
Note: There are still situations where this may not work. I don't know if Unity has this issue, but I know Ninject does. It actually uses the HttpContext.Current, to determine what request is active. So if you try to resolve something from the container later, like a service locator or factory then it may not be able to resolve.
I know this is an old question I have worked with option one (in the question) and, it works.
UPDATE: I deleted my answer as I realized I've posted something that doesn't work.
Sorry for any inconvenience.
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?
I don't think you should do this. Your service is a lower layer than your Api controller. Your service should not depend on any classes related to the higher layer, otherwise your service could not be reused, for example: when you need to build a win forms application on top of the existing services.
IPrincipal is not appropriate to be injected into our services as it's web application related . When we pass this information down to lower layers (service), we should pass our neutral-classes or just a userId to decouple our services from the application using it.
You should define your own classes for Users and anything request-related to be used in our services layer as it's more domain-related. With this, your service-layer is application-layer (web, win forms, console,..) agnostic:
public class AppPrincipal : IAppPrincipal
{
public int UserId { get; set; }
public string Role { get; set; }
//other properties
public AppPrincipal() {
}
public AppPrincipal(int userId, string role):this() {
UserId = userId;
Role = role;
}
}
Then you can register IAppPrincipal as per-request scope in your web application and populate all the properties using your IPrincipal. The will initialize your IAppPrincipal for your entire object graph before any await/async calls. Example code with Unity:
public void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IAppPrincipal>(
new PerRequestLifetimeManager(),
new InjectionFactory(c => CreateAppPrincipal()));
}
public IAppPrincipal CreateAppPrincipal()
{
var principal = new AppPrincipal();
principal.UserId = //Retrieve userId from your IPrincipal (HttpContext.Current.User)
principal.Role = //Retrieve role from your IPrincipal (HttpContext.Current.User)
return principal;
}
The key here is that we already decouple our service layer from the web. If you need to reuse your service layer to build a windows form or console application, you could register IAppPrincipal as singleton and populate it differently.
We don't need to deal with platform-related problems like async/await
Related
Started working on a windows background service in .net that will host a restful service. As I worked on it, it seemed like Minimal APIs were a good fit (it was one of the things I was able to get a working prototype with, I couldn't get other stuff to work). However, I'm not sure if I'm misunderstanding something here. When I inspect one of my injected services, I'm noticing that it's being reconstructed each time the endpoint is hit. I didn't think that would happen if I register my services as singletons. Something tells me that due to the nature of Minimal API, there is no way around that. Am I missing something?
I'm using MessagePipe for .net.
SquareService implements IAsyncRequestHandler<LocationByNameRequest, LocationResponse>
The registration.
builder.Services.AddMessagePipe();
builder.Services.AddSingleton<SquareService>();
The injection.
app.MapPut("/pos",
async (POS station,
IAsyncRequestHandler<LocationByNameRequest, LocationResponse> handler) => { ...});
I made sure that Visual Studio wasn't just randomly ouputing log messages, so I set up a GUID in the constructor to verify if the instances might be different (they are).
How else would I host an api in a windows service? Been having problems integrating this, and I think it's because I'm not getting the same references as I was expecting. Any guidance would be greatly appreciated.
That has nothing to do with Minimal APIs per se. First of all builder.Services.AddSingleton<SquareService>(); will register just SquareService, not the interfaces it implements, if you resolve SquareService in the handler you will get exactly the same instance every time:
app.MapPut("/pos", async (POS station, SquareService handler) => ...);
It seems that MessagePipe has it's own custom DI/Lifetime handling. For publishers/subscribers you manipulate the registration type individually by using corresponding interfaces - see this part of the doc:
I(Async)Publisher(Subscriber)'s lifetime is belonging MessagePipeOptions.InstanceLifetime. However if declare with ISingletonPublisher<TMessage>/ISingletonSubscriber<TKey, TMessage>, ISingletonAsyncPublisher<TMessage>/ISingletonAsyncSubscriber<TKey, TMessage> then used singleton lifetime. Also IScopedPublisher<TMessage>/IScopedSubscriber<TKey, TMessage>, IScopedAsyncPublisher<TMessage>/IScopedAsyncSubscriber<TKey, TMessage> uses scoped lifetime.
But for handlers the only option is to set it globally for all the handlers via MessagePipeOptions (docs):
Configure IRequestHandler/IAsyncRequestHandler's lifetime of DI container. You can choose Singleton or Scoped or Transient. Default is Scoped.
services.AddMessagePipe(options => options.RequestHandlerLifetime = InstanceLifetime.Singleton);
I'm maintaining a integration package that allows my users to integrate my library with ASP.NET Core. This package must be compatible with all versions of ASP.NET Core starting at 2.1. At application shutdown my integration package must be able to execute asynchronous cleanup, and unfortunately can't take a dependency on IAsyncDisposable through Microsoft.Bcl.AsyncInterfaces (see below).
The only way this, therefore, seems feasible is by registering an IHostedService implementation. It's StopAsync method is called at shutdown:
public sealed class ShutdownHostedService : IHostedService
{
public MyLibaryCleanupObject Obj;
public Task StartAsync(CancellationToken token) => Task.CompletedTask;
public Task StopAsync(CancellationToken token) => this.Obj.CleanupAsync();
}
services.AddSingleton<IHostedService>(new ShutdownHostedService { Obj = ... });
Application developers, however, can of course add their own IHostedService implementations, which might interact with my library. This is why it is important for my own IHostedService implementation to be called last. But here lies the problem.
With the introduction of ASP.NET Core 2.1 application developers can choose between using the new Microsoft.Extensions.Hosting.Host and the (now deprecated) Microsoft.AspNetCore.WebHost. With WebHost, at shutdown, IHostedService implementations are called in order of registration, whereas with Host, IHostedService implementations are called in opposite order of registration.
This is problematic for me, because my hosted service should be called last. As application developers might use my integration package in their existing ASP.NET Core application, they might still use WebHost, which is why it is important to support that scenario.
Question: What would be a reliable way to determine in what 'mode' the ASP.NET Core application runs, so I can decide to add my hosted service first or last?
Alternatively, to prevent falling into the XY-problem trap, I'm open to completely different solutions that solve my problem of implementing "asynchronous shutdown".
Note on IAsyncDisposable:
One solution that would come to mind (as Ian rightfully notes in the comments) is to add an IAsyncDisposable Singleton registration to the ServiceCollection. This would allow asynchronous cleanup at shutdown. Unfortunately, due to constraints (explained here) it's impossible for my integration package to take a dependency on Microsoft.Bcl.AsyncInterfaces and, therefore, not on IAsyncDisposable. This is an unfortunate situation that certainly complicates the matter. As a matter of fact, the reason for not being able to take a dependency on IAsyncDisposable is the reason I'm looking for alternative ways of implementing asynchronous shutdown code.
The solution I end up using is identical to the solution chosen by Microsoft's Microsoft.Extensions.Hosting.Internal.Host class and doesn't involve using IHostedService instances. The Host class contains the following Dispose method:
public void Dispose()
{
this.DisposeAsync().GetAwaiter().GetResult();
}
This might raise some eyebrows and might be seen as a bad practice, but don't forget that:
This code is guaranteed to run in the context of ASP.NET Core, where this code can't cause a deadlock
This code runs just once at shutdown, so performance isn't an issue here.
This is why Microsoft's Host class can take this approach, and it means that it is a safe approach for my library to do as well.
I have a WEB API application and I am using UnityContainer as my DI.
Since I'm using UnitOfWork with Entity Framework I wanted to register the DataContext in the UnityContainer per each request.
I was disappointed to find that no LifeTimeManager exists that can give me a new scope per request. After digging a little more, I found that Unity.AspNet.Mvc does contain a PerRequestLifetimeManager. My questions are:
Is there a reason why Unity doesn't contain a PerRequestLifetimeManager? It seems to me that is a very common case to register something per request.
Is there a particular reason why Unity.AspNet.Mvc does contain PerRequestLifetimeManager?
Is there something I need to know if I am using Unity.AspNet.Mvc in a WebApi project?
In case of using Thread or Tasks, how does the container knows it belongs to the same request?
Is there a reason why Unity doesn't contain a PerRequestLifetimeManager? It seems to me that is a very common case
to register something per request.
The core library is for .Net projects. Only Asp.Net would have a Request.
Is there a particular reason why Unity.AspNet.Mvc does contain
PerRequestLifetimeManager?
Same as answer 1. Requests are an Asp.Net concept.
Is there something I need to know if I am using Unity.AspNet.Mvc in a
WebApi project?
Nope. You will most likely only be using the PerRequestLifetimeManager anyway. I would imagine the developers of Unity didn't see a need to publish a Mvc and a WebApi package when the two libraries would have been identical.
In case of using Thread or Tasks, how does the container knows it
belongs to the same request?
The container is just another object. The .Net framework manages objects from request to request and thread to thread. The container itself creates a unique scope at the beginning of a request and destroys it at the end of the request .Net does everything in between.
I'm not quite sure when I should use SingletonScope() vs TransientScope() vs RequestScope() when I do my binding in my global.cs file.
I have for example my call to MongoSession (using NoRM and the mvcStarter project http://mvcstarter.codeplex.com/) which is set to SingletonScope but I created a repository that use this MongoSession object to make calls to Mongo easier, e.g., I have a NewsRepository which uses MongoSession to fetch my News items from the data. As an example I have a call that fetches News items that has DisplayOnHome set to true and get the latest by CreationDate. Should such a repository be SingletonScope or would RequestScope would be more appropriate?
When should I use each of it and why?
In general in a web app, you want state to be request scope as much as possible.
Only in the case of very low level optimisations are you ever likely to run into a case where its appropriate to create singleton objects (and the chances even then are that you'll pull such caching / sharing logic out into another class which gets pulled in as a dependency on your other [request scope] objects and make that singleton scope). Remember that a singleton in the context of a web app means multiple threads using the same objects. This is rarely good news.
On the same basis, transient scope is the most straightforward default (and that's why Ninject 2 makes it so) - request scope should only come into the equation when something needs to be shared for performance reasons, etc. (or because that's simply the context of the sharing [as mentioned in the other answer]).
I guess the answer would depend on whether your MongoSession represents a unit of work or not. Most database related classes that I've worked with (mostly in the context of ORM, such as NHibernate or EF4) revolve around a context, entities, and tracked state that represent a unit of work. A unit of work should never be kept around longer than the length of time required to perform the given unit of work, after which the unit should be committed or rolled back. That would mean you should use RequestScope.
If your MongoSession is not a unit of work, you could keep it around for the lifetime of an MVC session, in which case SessionScope would then be appropriate.
From deleted question as requested by #shankbond above
The Disposal is not necessarily performed synchronously on your main request thread as one might assume.
You probably want to stash a Block and then Dispose() it at an appropriate phase in your request (how are you going to handle exceptions?)
Have a look in the Ninject Tests for more examples (seriously, go look - they're short and clear and I didnt regret it when I listened the 3rd time I was told to!)
See http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/
I am having this issue too, Lately, I started working on MongoDB. MongoDB recommends singleton for MongoClient. So I am still not sure about my implementation, and I am confused. I implemented the Mongo in the DI container two ways, and I am not sure which one is good. Let's take the first approach
Here I return a singleton instance of IMongoClient
services.AddSingleton(_ =>
{
return new MongoClient(con.ConnectionString);
});
Then,
services.AddScoped<IMongoDatabase>(s =>
{
var client = p.GetRequiredService<IMongoClient>();
return client.GetDatabase(con.DatabaseName);
});
Then, return a scoped for my IMongoDatabase. In my repo, I inject the IMongoDatabaseand then call my DB.
_dataContext = mongoDBClient.GetCollection<SomeCollection>(GetCollectionNameFromAppSetting((settings.DPUBotCollectionName)));
The second one I was returning an IMongoDatabase as a singleton:
services.AddSingleton<IMongoDatabase>(_ =>
{
//var connectionString = con;
return new
MongoClient(con.ConnectionString).GetDatabase("SomeDatabase");
});
Monog says their MonogClient and IMongoDatabase are thread-safe. I am not sure which approach is right. I would appreciate it if you could give me an answer.
First off, I wish context based storage was consistent across the framework!
With that said, I'm looking for an elegant solution to make these properties safe across ASP.NET, WCF and any other multithreaded .NET code. The properties are located in some low-level tracing helpers (these are exposed via methods if you're wondering why they're internal).
I'd rather not have a dependency on unneeded assemblies (like System.Web, etc). I don't want to require anyone using this code to configure anything. I just want it to work ;) That may be too tall of an order though...
Anyone have any tricks up their sleeves? (I've seen Spring's implementation)
internal static string CurrentInstance
{
get
{
return CallContext.LogicalGetData(currentInstanceSlotName) as string;
}
set
{
CallContext.LogicalSetData(currentInstanceSlotName, value);
}
}
internal static Stack<ActivityState> AmbientActivityId
{
get
{
Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>;
if (stack == null)
{
stack = new Stack<ActivityState>();
CallContext.LogicalSetData(ambientActivityStateSlotName, stack);
}
return stack;
}
}
Update
By safe I do not mean synchronized. Background on the issue here
Here is a link to (at least part of) NHibernate's "context" implementation:
https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/
It is not clear to me exactly where or how this comes into play in the context of NHibernate. That is, if I wanted to store some values in "the context" would I get "the context" from NHibernate and add my values? I don't use NHibernate, so I don't really know.
I suppose that you could look and determine for yourself if this kind of implementation would be useful to you. Apparently the idea would be to inject the desired implementation, depending on the type of application (ASP.NET, WCF, etc). That probably implies some configuration (maybe minimal if one were to use MEF to load "the" ICurrentSessionContext interface).
At any rate, I found this idea interesting when I found it some time ago while searching for information on CallContext.SetData/GetData/LogicalSetData/LogicalGetData, Thread.SetData/GetData, [ThreadStatic], etc.
Also, based on your use of CallContext.LogicalSetData rather than CallContext.SetData, I assume that you want to take advantage of the fact that information associated with the logical thread will be propagated to child threads as opposed to just wanting a "thread safe" place to store info. So, if you were to set (pr Push) the AmbientActivity in your app's startup and then not push any more activities, any subsequent threads would also be part of that same activity since data stored via LogicalSetData is inherited by child threads.
If you have learned anything in the meantime since you first asked this question I would be very interested in hearing about it. Even if you haven't, I would be interested in learning about what you are doing with the context.
At the moment, I am working on maintaining some context information for logging/tracing (similar to Trace.CorrelationManager.ActivityId and Trace.CorrelationManager.LogicalOpertionStack and log4net/NLog context support). I would like to save some context (current app, current app instance, current activity (maybe nested)) for use in an app or WCF service AND I want to propagate it "automatically" across WCF service boundaries. This is to allow logging statements logged in a central repository to be correlated by client/activity/etc. We would be able to query and correlate for all logging statements by a specific instance of a specific application. The logging statements could have been generated on the client or in one or more WCF services.
The WCF propagation of ActivityId is not necessarily sufficient for us because we want to propagate (or we think we do) more than just the ActivityId. Also, we want to propagate this information from Silverlight clients to WCF services and Trace.CorrelationManager is not available in Silverlight (at least not in 4.0, maybe something like it will be available in the future).
Currently I am prototyping the propagation of our "context" information using IClientMessageInspector and IDispatchMessageInspector. It looks like it will probably work ok for us.
Regarding a dependency on System.Web, the NHibernate implementation does have a "ReflectiveHttpContext" that uses reflection to access the HttpContext so there would not be a project dependency on System.Web. Obviously, System.Web would have to be available where the app is deployed if HttpContext is configured to be used.
I don't know that using CallContext is the right move here if the desire is simply to provide thread-safe access to your properties. If that is the case, the lock statement is all you need.
However, you have to make sure you are applying it correctly.
With CallContext, you are going to get thread-safe access because you are going to have separate instances of CallContext when calls come in on different threads (or different stores, rather). However, that's very different from making access to a resource thread-safe.
If you want to share the same value across multiple threads, then the lock statement is the way to go. Otherwise, if you want specific values on a per-thread/call basis, use the CallContext, or use the static GetData/SetData methods on the Thread class, or the ThreadStatic attribute (or any number of thread-based storage mechanisms).