I have an MVC core app that references a .NET Core class library. All of the data access and business logic is in the class library. How can I can I access the authenticated user from the class library?
In the past using .NET Framework you could use
string UserName = System.Web.HttpContext.Current.User.Identity.Name
To get the username from inside a method in the class library. In .NET Core, it appears that HttpContext no longer has a Current or User property.
Here's a simple use case. Suppose I have a data entity and service that "stamps" entities with the date and username before saving them to the database.
These would be in the external class library:
public interface IAuditable{
DateTime CreateDate{get;set;}
string UserName{get;set;}
}
public class MyEntity:IAuditable{
public int ID{get;set;}
public string Name{get;set;}
public string Information{get;set;}
}
public static class Auditor{
public static IAuditable Stamp(IAuditable model){
model.CreateDate=DateTime.UtcNow;
model.CreatedBy=System.Web.HttpContext.Current.User.Identity.Name;
return model;
}
}
public sealed class MyService:IDisposable{
MyDb db=new MyDb();
public async Task<int> Create(MyEntity model){
Auditor.Stamp(model);
db.MyEntities.Add(model);
return await db.SaveAsync();
}
public void Dispose(){
db.Dispose();
}
}
Then in my MVC controller I'd have a post action that calls the service:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(MyEntity model)
{
await service.Create(model);
return RedirectToAction("Index")
}
I would like a way to replace that line in Auditor.Stamp since there's no HttpContext.Current in .NET Core, apparently.
This post gives an example of how to get the username in Core:
public class UserResolverService
{
private readonly IHttpContextAccessor _context;
public UserResolverService(IHttpContextAccessor context)
{
_context = context;
}
public string GetUser()
{
return await _context.HttpContext.User?.Identity?.Name;
}
}
But I'm left with another version of the same problem: how do I get a IHttpContextAccessor object from inside the class library?
Most of my search results only deal with the question of how to get the User name from inside an MVC controller method. In the past I've passed a User object into every method for every service but that's a lot of extra typing--I'd rather have something I can type once (maybe inside Startup?) And then forget about it.
I do want something I can mock for unit tests, but honestly I think wrapping System.Web.HttpContext.Current.User.Identity.Name in something that can be mocked was pretty darn easy.
IHttpContextAccessorand you have access to what you need. - Nkosi