Search code examples
c#autofacaudit.net

Audit.NET Adding UserName to AuditLog when logging EF but can't reach HttpContext


Context

I am trying wireup Audit.Net in an MVC5 app with .Net Framework 4.8.

Dataprovider: EntityFramework

Output: Cosmos

DI Provider: Autofac

The Problem

I have tried the following call backs to try and write the username to the AuditEvent.

Configuration.AddOnCreatedAction(scope =>
{
    var username = HttpContext.Current.User.Identity.GetUserId();
    scope.SetCustomField("User2", username);
});
Configuration.AddOnSavingAction(scope =>
{
    var username = HttpContext.Current.User.Identity.GetUserId();
    scope.SetCustomField("User2", username);
});
Configuration.AddOnSavingAction(scope =>
{
    var user = AutofacDependencyResolver.Current.Resolve<IPrincipal>();
    scope.SetCustomField("User2", user.Identity.GetUserId());
});

These for work for synchronous calls to dbContext.SaveChanges(), when SaveChangesAsync() is called then I cannot access the current HttpContext as it is always null.

Any suggestions?


Solution

  • The key (which might help in search terms) is async. A quick search for async httpcontext mvc gets us to this existing question with a lot of information about async/await and HttpContext usage.

    The super short version: in MVC, the HttpContext gets carried around in the thread synchronization context (which is also where, say, the culture and other thread settings are carried around) but it's expensive to cart that context from thread to thread so the default is to not do that. You need to enable it explicitly to work.

    Here's a blog article explaining the various knobs you can turn in web.config to get it to work but the net result is, basically, to make sure <httpRuntime targetFramework="4.5" /> is set (well, set that value to 4.5 or higher).

    If that's already set, then... maybe there's something else at play, like a call has the ConfigureAwait(false) set on it so it's not returning to a thread context that has the HttpContext. But, more than likely, that httpRuntime flag should fix it.