控制器构造函数中Identity User值为null的解决方法
问题根因
ASP.NET MVC 生命周期中,控制器实例化发生在请求上下文绑定之前,此时Controller类的User属性还未被赋值,自然取到null。另外你当前代码保留了无参构造函数,Autofac解析时存在优先调用无参构造导致DbContext注入失败的隐患。
TrackerEnabledDbContext的ConfigureUsername方法接收的是Func<string>类型的延迟执行委托,只有实际写入审计日志时才会调用该委托获取用户名,根本不需要在控制器构造阶段就拿到用户值。
推荐解决方案(全局配置,无重复代码)
直接把用户名配置逻辑移到Autofac的DbContext注册阶段,委托从当前请求的HttpContext取用户信息即可,审计触发时请求上下文已经完全初始化,能正常拿到身份信息。
- 修改Global.asax中的Autofac注册代码:
builder.Register(c => { var context = new MyDbContext(); // 配置延迟取值委托,审计记录生成时才会执行取值逻辑 context.ConfigureUsername(() => HttpContext.Current?.User?.Identity?.Name ?? "Anonymous" ); return context; }).AsSelf().InstancePerRequest();
- 清理控制器代码,删除无参构造和构造函数内的审计配置逻辑,避免重复代码和注入异常:
public class MyController : Controller { private readonly MyDbContext db; public MyController(MyDbContext db) { this.db = db; } // 后续业务Action逻辑保持不变 }
这种写法把审计配置全局收敛在注入层,后续不管是控制器、业务服务层、过滤器里用到MyDbContext,都会自动带审计配置,不需要每个地方重复写配置代码。
临时兼容方案(控制器内配置)
如果因为特殊场景必须在控制器内完成配置,就把配置逻辑从构造函数移到控制器的Initialize方法中,该方法执行时请求上下文已经绑定完成,User属性已赋值:
public class MyController : Controller { private readonly MyDbContext db; public MyController(MyDbContext db) { this.db = db; } protected override void Initialize(System.Web.Routing.RequestContext requestContext) { base.Initialize(requestContext); // 此处User属性已完成初始化,可正常取值 db?.ConfigureUsername(() => User.Identity.Name); } }
注意:该方案需要所有使用MyDbContext的控制器都重写Initialize方法,重复代码多,维护成本高,仅适合小项目临时使用。
内容的提问来源于stack exchange,提问作者user3634071
相关产品推荐
相关产品推荐

