Audit.NET 在记录 EF 但无法访问 HttpContext 时将 UserName 添加到 AuditLog
Audit.NET Adding UserName to AuditLog when logging EF but can't reach HttpContext
上下文
我正在使用 .Net Framework 4.8 在 MVC5 应用程序中尝试接线 Audit.Net。
数据提供者:EntityFramework
输出:Cosmos
DI 提供商:Autofac
问题
我尝试了以下回调来尝试将用户名写入 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());
});
这些用于同步调用 dbContext.SaveChanges(),当调用 SaveChangesAsync() 时,我无法访问当前的 HttpContext,因为它始终为 null。
有什么建议吗?
关键字(可能有助于搜索字词)是 async
。快速搜索 async httpcontext mvc
让我们找到 ,其中包含大量关于 async
/await
和 HttpContext
用法的信息。
超短版本:在 MVC 中,HttpContext
在线程同步上下文中被携带(这也是文化和其他线程设置被携带的地方)但是购物很昂贵该上下文从一个线程到另一个线程,因此默认设置是 不这样做 。 您需要明确启用它才能工作。
Here's a blog article explaining the various knobs you can turn in web.config to get it to work 但最终结果基本上是确保 <httpRuntime targetFramework="4.5" />
已设置(好吧,将该值设置为 4.5 或更高 )。
如果 已经 设置了,那么...也许还有其他原因,比如呼叫设置了 ConfigureAwait(false)
所以它不会返回到具有 HttpContext
的线程上下文。但是,更有可能的是,httpRuntime
标志应该可以修复它。
您可以在 Asp .Net 管道中更早地捕获 HttpContext:
public interface IHttpContextContainer
{
HttpContextBase HttpContextBase { get; set; }
}
在您的控制器或服务中,您可以将生命周期范围附加到您的自定义审计事件:
public abstract class MyAuditEvent : AuditEvent
{
[JsonIgnore]
public ILifetimeScope LifetimeScope { get; set; }
}
添加 JsonIgnoreAttribute 以防止序列化 LifetimeScope。
在全局事件处理程序中,您现在可以访问自定义审计事件:
Configuration
.AddCustomAction(
ActionType.OnScopeCreated,
auditScope =>
{
if (auditScope.Event is MyAuditEvent auditEvent)
{
var scope = auditEvent.LifetimeScope;
var httpContextContainer = scope.Resolve<IHttpContextContainer>();
// ...
// access HttpContextBase from httpContextContainer
}
});
上下文
我正在使用 .Net Framework 4.8 在 MVC5 应用程序中尝试接线 Audit.Net。
数据提供者:EntityFramework
输出:Cosmos
DI 提供商:Autofac
问题
我尝试了以下回调来尝试将用户名写入 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());
});
这些用于同步调用 dbContext.SaveChanges(),当调用 SaveChangesAsync() 时,我无法访问当前的 HttpContext,因为它始终为 null。
有什么建议吗?
关键字(可能有助于搜索字词)是 async
。快速搜索 async httpcontext mvc
让我们找到 async
/await
和 HttpContext
用法的信息。
超短版本:在 MVC 中,HttpContext
在线程同步上下文中被携带(这也是文化和其他线程设置被携带的地方)但是购物很昂贵该上下文从一个线程到另一个线程,因此默认设置是 不这样做 。 您需要明确启用它才能工作。
Here's a blog article explaining the various knobs you can turn in web.config to get it to work 但最终结果基本上是确保 <httpRuntime targetFramework="4.5" />
已设置(好吧,将该值设置为 4.5 或更高 )。
如果 已经 设置了,那么...也许还有其他原因,比如呼叫设置了 ConfigureAwait(false)
所以它不会返回到具有 HttpContext
的线程上下文。但是,更有可能的是,httpRuntime
标志应该可以修复它。
您可以在 Asp .Net 管道中更早地捕获 HttpContext:
public interface IHttpContextContainer
{
HttpContextBase HttpContextBase { get; set; }
}
在您的控制器或服务中,您可以将生命周期范围附加到您的自定义审计事件:
public abstract class MyAuditEvent : AuditEvent
{
[JsonIgnore]
public ILifetimeScope LifetimeScope { get; set; }
}
添加 JsonIgnoreAttribute 以防止序列化 LifetimeScope。
在全局事件处理程序中,您现在可以访问自定义审计事件:
Configuration
.AddCustomAction(
ActionType.OnScopeCreated,
auditScope =>
{
if (auditScope.Event is MyAuditEvent auditEvent)
{
var scope = auditEvent.LifetimeScope;
var httpContextContainer = scope.Resolve<IHttpContextContainer>();
// ...
// access HttpContextBase from httpContextContainer
}
});