ASP.NET Core Entity changing history

asp.net-core audit.net audit-logging entity-framework-core

Question

I have many controllers like this:

public class EntityController : Controller
{
    private readonly IEntityRepository _entity;

    public EntityController(IEntityRepository entity)
    {
        _entity = entity;
    }

    [Authorize]
    [HttpPut("{id}")]
    public async ValueTask<IActionResult> Put(int id, [FromBody] Entity entity)
    {
        if (entity == null || entity.Id != id) return BadRequest();
        var updated = await _entity.Update(entity);
        if (updated == null) return NotFound();
        return Ok(updated);
    }
}

I need to implement entities editing (audit) history.

And, since the method is marked as [Authorize], I need to log by which user it was edited. I'm looking at Audit.NET, but I didn't find a way to do it.

1
2
12/13/2019 4:10:08 AM

Accepted Answer

The Audit.NET EF Provider allows to customize the audit entity before saving it. This has to be done at the startup with a so-called AuditEntity Action: an action that is triggered for each entity being modified.

So, you can make this action retrieve the user name from the current HttpContext and store it in a UserName property on your audit entities.

On your asp net startup code, setup a way to obtain the current HttpContext and configure the action to retrieve the username from the context:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add the HttpContextAccessor if needed.
        services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        // Get the service provider to access the http context
        var svcProvider = services.BuildServiceProvider();

        // Configure Audit.NET
        Audit.Core.Configuration.Setup()
            .UseEntityFramework(x => x
                .AuditTypeNameMapper(typeName => "Audit_" + typeName)
                .AuditEntityAction((evt, ent, auditEntity) =>
                {
                    // Get the current HttpContext 
                    var httpContext = svcProvider.GetService<IHttpContextAccessor>().HttpContext;
                    // Store the identity name on the "UserName" property of the audit entity
                    ((dynamic)auditEntity).UserName = httpContext.User?.Identity.Name;
                }));
    }
}

This is assuming your audit entities have a common UserName property.

If your Audit Entities already inherits from an interface or base class including the UserName, you can use the generic AuditEntityAction<T> instead.

Audit.Core.Configuration.Setup()
    .UseEntityFramework(x => x
        .AuditTypeNameMapper(typeName => "Audit_" + typeName)
        .AuditEntityAction<IUserName>((evt, ent, auditEntity) =>
        {
            var httpContext = svcProvider.GetService<IHttpContextAccessor>().HttpContext;
            auditEntity.UserName = httpContext.User?.Identity.Name;
        }));
5
4/17/2018 2:43:45 AM

Popular Answer

To get UserID in IOC :

var userId = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value 

how-get-current-user-in-asp-net-core



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow