In the solution that I’m migrating to ASP.NET Core, I have a domain project that uses System.Web’s HttpContext. Since System.Web is not part of .NET Core, I had to figure out how one gets the current user’s identity within a domain class.
Fortunately, with .NET Core’s built-in DI, this is pretty easy. HttpContext access has been abstracted into a set of abstractions (yeah, that sounds redundant) in this package:
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0"
Once this package is added to the domain project, the constructor of whatever class that needs HttpContext needs to be modified. My class is called CurrentUserService. The constructor and a few private accessors are all that are needed. Then, we can access the User and Identity objects from the HttpContext.
private IHttpContextAccessor _contextAccessor; private HttpContext _context { get { return _contextAccessor.HttpContext; } } public CurrentUserService(IHttpContextAccessor contextAccessor) { _contextAccessor = contextAccessor; } public string UserName { get { var userName = "SystemGenerated"; // Figure out the user's identity if (_context != null) { if (_context.User != null) { var identity = _context.User.Identity; if (identity != null && identity.IsAuthenticated) { userName = identity.Name; } } } return userName; }
While the code above shows getting the Name for the current identity, we could also access any claim by casting the Identity to a ClaimsIdentity.
In the web project, the IHttpContextAccessor needs to be specified for injection as a transient singleton so that we get one per request. This is performed in the Startup.cs’s ConfigureServices method.
* Update: IHttpContextAccessor should be registered as a singleton. If it’s not registered as a singleton, you will have unpredictable behavior.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
After making these changes, the ported domain project’s code works as expected.
I’m afraid the code above wouldn’t work, or at the very least, work unreliably. The IHttpContextAccessor should be registered as a singleton; https://github.com/aspnet/Hosting/issues/793
You are correct. I did actually experience this first hand, but had not updated the article to reflect this behavior. I use this in all of my apps: