If you have been using .NET Core, then you know that Dependency Injection is rather important in this new ecosystem. Thankfully, the development team made it incredibly easy to use.
One common scenario that I have seen arise since its release, has been something to the extent of:
"How can I inject Identity or User information via D.I. in .NET Core?"
This could be a common use case for systems that require identity information for server-level transactions (e.g. when creating a new entity, you might want to know who performed this action or likewise if you wanted to audit who accessed a particular record in your system).
This post will cover implementing such services that you can easily use or extend within your applications; which you have probably tried already, but didn't work.
The most common place that you'll see developers go to access the current user might be as simple as the User.Identity property that is exposed from the HttpContext. However, if you are reading this post, I'm sure that you have attempted something like the following.
-
- public FooController(FooContext context)
- {
-
- _context = context;
-
- _user = HttpContext.User?.Identity?.Name;
- }
You'll quickly find that the actual HttpContext doesn't exist within the constructor for the Controller (and isn't created until further down the pipeline).
So, in order for us to actually access anything within the HttpContext, we will need to explicitly inject it. Thankfully, that isn't too difficult to do.
Building a Service to Inject the HttpContext
For D.I. to work, we will need to build a service that can inject the HttpContext that we need in the pipeline so that we can access the properties of it.
We can do this by creating a simple class that already injects that information into it, behind the scenes via 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.
- 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();
- }
- }
And, that's basically it.
Extending the Service
If you had some additional properties that existed on the ApplicationUserobject (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 obviously just a starting point for building a service that leverages the existing context (enabling all sorts of context-sensitive logic), but hopefully it will pique your interest in developing your own services to pass around.