Accessing Identity and HttpContext Info using Dependency Injection in Asp.Net Core
Dependency injection is important factor in asp.net core ecosystem. The Development team has made it really easy to use. This could be a common use case for systems that require identity information for server-level transactions. For example if you are creating a new entity then you might want to know who performed this action or likewise if you wanted to audit who accessed a particular record in your system.
The Developers mostly access the current user might be as simple as the User.Identity property that is exposed from the HttpContext. For example Something like this:
public FooController(FooContext context)
{
// Injecting your data context (a common-use case)
_context = context;
// Attempting to resolve the current user
_user = HttpContext.User?.Identity?.Name;
}
Here we can see that the actual HttpContext doesn’t exist within the constructor for the controller.
So in order to actually access anything within the HttpContext, we need to explicitly inject it which is not too difficult to do.
Building a Service to Inject the HttpContext
For Dependency Injection to work, we need to build a service that can inject the HttpContext into the pipeline so that we can access properties of it.
We can achieve that by creating a simple class that already injects that information into it behind the scenes through a IHttpContextAccessor object as seen below :
public class UserResolverService
{
private readonly IHttpContextAccessor _context;
public UserResolverService(IHttpContextAccessor context)
{
_context = context;
}
public string GetUser()
{
return await _context.HttpContext.User?.Identity?.Name;
}
}
What this will do is inject the HttpContext
object from a request into this UserResolverService
, which will store the context and expose a method called GetUser()
that will return the current name of the user.
This might be used within a repository if you needed to store the username that was accessing a particular record as follows :
public class FooRepository : IFooRepository
{
private FooContext _context;
private string _currentUser;
public FooRepository(FooContext context, UserResolverService userService)
{
_context = context;
_currentUser = userService.GetUser();
}
public void DoWork()
{
var widget = new Widget(){
Id = 42,
Title = "The Answer",
Author = "Deepthought",
CreatedBy = _currentUser
};
_context.Widgets.Add(widget);
_context.SaveChanges();
}
}
Extending the Service
If you had some additional properties that existed on the ApplicationUser
object (the abstraction that Entity Framework uses by default), then you might want to extend this service to pass along the entire object itself. Doing this would require a very minor change, as you would simply need to inject your UserManager
object into this new service :
public class UserResolverService
{
private readonly IHttpContextAccessor _context;
private readonly UserManager<ApplicationUser> _userManager;
public UserResolverService(IHttpContextAccessor context, UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
}
public async Task<ApplicationUser> GetUser()
{
return await _userManager.FindByEmailAsync(_context.HttpContext.User?.Identity?.Name);
}
}
This is just a starting point for bulding a service that leverages the existing context but hopefully this will high up your interest in developing your own services to pass around.