代码之家  ›  专栏  ›  技术社区  ›  A J Qarshi

Web API-访问DbContext类内的HttpContext

  •  4
  • A J Qarshi  · 技术社区  · 8 年前

    在我的C#Web API应用程序中,我添加了 CreatedDate CreatedBy 所有表中的列。现在,我想在任何表中添加新记录时填充这些列。

    为此,我已覆盖 SaveChanges SaveChangesAsync DbContext类中的函数如下:

    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;
                    }                
                }
            }
        }
    }
    

    现在当我打电话的时候 保存更改 保存更改同步 从我的控制器中的任何位置, HttpContext.Current 已分配,我可以使用 ttpContext.Current.User.Identity.Name 。但当我使用 UserManager.UpdateAsync 函数(内部调用 保存更改同步 函数)对底层用户表进行更改, HttpContext。现在的 设置为null。

    在这种情况下,如何访问HttpContext来获取用户名?

    1 回复  |  直到 8 年前
        1
  •  4
  •   StaceyGirl    8 年前

    问题是 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
      }
    }