注入CurrentUserService到DbContext后控制器中UserId始终为null如何解决
问题根因
你遇到的问题核心是CurrentUserService的UserId赋值时机错误:
- 你在服务构造函数中直接读取
HttpContext.User获取用户ID,但这个属性只有在ASP.NET Core身份认证中间件执行完成后才会被正确填充。 DbContext作为Scoped服务,其构造时机远早于控制器的构造时机、也早于身份认证中间件的执行阶段,此时注入的CurrentUserService在构造时读取到的User是空值,导致UserId被永久赋值为null,这和你调整服务生命周期没有关联。
解决方案
第一步:修改CurrentUserService为动态取值
不要在构造函数中提前读取并固定UserId的值,改为每次访问属性时动态从当前HttpContext中读取:
public class CurrentUserService : ICurrentUserService { private readonly IHttpContextAccessor _httpContextAccessor; public CurrentUserService(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } // 动态取值,每次访问时读取最新的用户身份信息 public string UserId => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); }
第二步:调整DbContext中UserId的读取时机
不要在AppDbContext的构造函数中访问_currentUserService.UserId,如果有审计字段自动赋值等需求,将逻辑迁移到SaveChanges/SaveChangesAsync方法中,这些方法执行时已经处于请求处理阶段,身份认证已完成,可以拿到正确的用户ID:
public class AppDbContext:IdentityDbContext<AppUser>,IAppDbContext { private readonly ICurrentUserService _currentUserService; public AppDbContext(DbContextOptions<AppDbContext> options, ICurrentUserService currentUserService):base(options) { _currentUserService = currentUserService; } public override int SaveChanges() { ProcessAuditFields(); return base.SaveChanges(); } public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { ProcessAuditFields(); return base.SaveChangesAsync(cancellationToken); } private void ProcessAuditFields() { // 示例:给所有实现了审计接口的实体自动赋值操作人 foreach (var entry in ChangeTracker.Entries<IAuditable>()) { var userId = _currentUserService.UserId; if (entry.State == EntityState.Added) { entry.Entity.CreatorId = userId; entry.Entity.CreateTime = DateTime.Now; } else if (entry.State == EntityState.Modified) { entry.Entity.UpdaterId = userId; entry.Entity.UpdateTime = DateTime.Now; } } } }
额外检查项
- 确认Program.cs中已经注册了
IHttpContextAccessor:builder.Services.AddHttpContextAccessor(); CurrentUserService和AppDbContext都保持Scoped生命周期即可,无需修改为Transient。
内容的提问来源于stack exchange,提问作者Engel
相关产品推荐
相关产品推荐

