C# Web API-在DbContext类中访问HttpContext
在我的C#Web API应用程序中,我在所有表中添加了C# Web API-在DbContext类中访问HttpContext,c#,asp.net-web-api,C#,Asp.net Web Api,在我的C#Web API应用程序中,我在所有表中添加了CreatedDate和CreatedBy列。现在我想在任何表中添加新记录时填充这些列 为此,我在DbContext类中重写了SaveChanges和savechangesync函数,如下所示: public class AuthDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUs
CreatedDate
和CreatedBy
列。现在我想在任何表中添加新记录时填充这些列
为此,我在DbContext类中重写了SaveChanges
和savechangesync
函数,如下所示:
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;
}
}
}
}
}
公共类AuthDbContext:IdentityDbContext
{
公共覆盖int SaveChanges()
{
AddTimestamps();
返回base.SaveChanges();
}
公共重写异步任务SaveChangesAsync()
{
AddTimestamps();
return wait base.SaveChangesAsync();
}
私有void AddTimestamps()
{
var entities=ChangeTracker.Entries(),其中(x=>(x.State==EntityState.Added));
var currentUsername=!string.IsNullOrEmpty(HttpContext.Current?.User?.Identity?.Name)
?HttpContext.Current.User.Identity.Name
:“系统”;
foreach(实体中的var实体)
{
foreach(entity.CurrentValues.PropertyNames中的变量propName)
{
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
或savechangesync
时,HttpContext.Current
被分配,我可以使用ttpContext.Current.User.Identity.name
从中获取用户名。但是,当我使用UserManager.UpdateAsync
函数(在DbContext类中内部调用savechangesync
函数)对底层用户表进行更改时,HttpContext.Current
设置为null
在这种特殊情况下,我如何访问HttpContext来获取用户名?问题是,使用
savechangesync
时,您不知道是否可以访问HttpContext.Current
,因为您可能没有在处理请求的线程上执行
解决这个问题的最好方法是使用DI。您可以在实现依赖于HttpContextBase
的位置创建接口和匹配类。配置DI框架,将IUserContext
实例注入到DbContext
中,并为每个请求创建UserContext
的新实例
至于使用哪种DI框架,我是偏爱的,但有很多可供选择,而且大部分都有类似的功能
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
}
}
你怎么称呼UpdateAsync?你能展示一下吗?作为旁注,我强烈建议你定义一个接口,比如说
IAuditable
,它声明有问题的属性,而不是乱搞字符串。同时使用DateTime.Now
几乎肯定会对你造成伤害。@AluanHaddad,你对使用DateTime.Now的评论是什么意思,你的意思是他应该使用DateTime.UtcNow吗?@Mart10是的,如果这足够的话,可以使用DateTime.UtcNow
(也就是说,你永远不需要在当地时间显示它们)否则,您需要使用DateTimeOffset
,并保留一个时区。@AluanHaddad完全同意您的意见。感谢您的指导+1感谢Igor。这与您在另一个问题的评论中所建议的类似。asp.net web api不支持现成的DI吗?还是仅仅是aspnetcore?@Mart10-core是一个内置DI框架的内核。Asp.net(web api/mvc)没有内置框架,但添加第三方di框架非常容易。