There are some ways this can be accomplished, but ultimately it will depend on your specific use case.
If you can't (or don't want to) change your DbContext
, you can have a custom action to resolve the HTTP context accessor from the DbContext.
For example, in your program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
// Create the custom action to override the UserName
Audit.Core.Configuration.AddOnCreatedAction(scope =>
{
// Get the HTTP context accessor
var ctxAccessor = scope.GetEntityFrameworkEvent().GetDbContext().GetService<IHttpContextAccessor>();
// Get the user name
var userName = ctxAccessor.HttpContext.User.FindFirst(ClaimTypes.Name)?.Value;
// Override the environment's user name
scope.Event.Environment.UserName = userName;
// Or set a custom field with it
scope.SetCustomField("UserName", userName);
});
app.Run();
Another way, assuming your audited DbContext
inherits from AuditDbContext
, is to Inject the IHttpContextAccessor
to your DbContext
constructor (or use the GetService extension method) to retrieve the user and set a custom audit field with the username.
For example:
public class YourDbContext : AuditDbContext
{
public YourDbContext(DbContextOptions<YourDbContext> options, IHttpContextAccessor contextAccessor) : base(options)
{
var user = contextAccessor.HttpContext.User.FindFirst(ClaimTypes.Name);
this.AddAuditCustomField("UserName", user);
}
// ...
}
or just:
public class YourDbContext : AuditDbContext
{
public YourDbContext(DbContextOptions<YourDbContext> options) : base(options)
{
var ctxAccessor = this.GetService<IHttpContextAccessor>();
var user = ctxAccessor.HttpContext.User.FindFirst(ClaimTypes.Name);
this.AddAuditCustomField("UserName", user);
}
// ...
}