在我的C#Web API应用程序中,我在所有表中添加了CreatedDate
和CreatedBy
列。现在,我想在任何表中添加新记录时填充这些列。
为此,我在DbContext类中重写了SaveChanges
和SaveChangesAsync
函数,如下所示:
public class AuthDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public override int SaveChanges()
{
AddTimestamps();
return base.SaveChanges();
}
public override async Task<int> SaveChangesAsync()
{
AddTimestamps();
return await base.SaveChangesAsync();
}
private void AddTimestamps()
{
var entities = ChangeTracker.Entries().Where(x => (x.State == EntityState.Added));
var currentUsername = !string.IsNullOrEmpty(HttpContext.Current?.User?.Identity?.Name)
? HttpContext.Current.User.Identity.Name
: "SYSTEM";
foreach (var entity in entities)
{
foreach (var propName in entity.CurrentValues.PropertyNames)
{
if (propName == "CreatedBy" && entity.State == EntityState.Added)
{
entity.CurrentValues[propName] = currentUsername;
}
else if (propName == "CreatedDate" && entity.State == EntityState.Added)
{
entity.CurrentValues[propName] = DateTime.Now;
}
}
}
}
}
现在,当我从控制器的任何位置拨打SaveChanges
或SaveChangesAsync
时,HttpContext.Current
已分配,我可以使用ttpContext.Current.User.Identity.Name
从中获取用户名。但是当我使用UserManager.UpdateAsync
函数(在我们的DbContext类中内部调用SaveChangesAsync
函数)来更改底层用户表时,HttpContext.Current
被设置为null。
如何在此特定情况下访问HttpContext以获取用户名?
答案 0 :(得分:4)
问题是使用SaveChangesAsync
您不知道您是否有权访问HttpContext.Current
,因为您可能没有在请求被提供的线程上执行。
解决这个问题的最佳方法是使用DI。您可以创建一个接口和匹配类,其中实现依赖于HttpContextBase
。配置DI框架以将IUserContext
实例注入DbContext
并为每个请求创建UserContext
的新实例。
至于使用哪个DI框架,我偏向于Autofac,但有很多可供选择,并且大部分具有相似的功能。
public interface IUserContext {
bool IsAuthenticated {get;}
// additional properties like user id / name / etc
}
public class UserContext : IUserContext
{
public UserContext(HttpContextBase httpContext) {
this.IsAuthenticated = httpContext.User.Identity.IsAuthenticated;
// any other properties that you want to use later
}
}