.NET 4.8项目DI部署后突发Value cannot be null. Parameter name: provider错误
.NET 4.8依赖注入生产环境突发空引用异常排查与修复
问题场景
在.NET 4.8项目中引入Microsoft DependencyInjection NuGet包并完成DI配置后,生产环境运行数天无异常,但Elmah日志突然大量出现来自Application_BeginRequest方法的错误:
Value cannot be null. Parameter name: provider
现有DI配置代码
Startup.cs
[assembly: OwinStartupAttribute(typeof(Account.Startup))] namespace Account { public partial class Startup { public void Configuration(IAppBuilder app) { ServiceCollection services = new ServiceCollection(); //添加多个依赖项... //创建服务提供器 IServiceProvider serviceProvider = services.BuildServiceProvider(); //保存到静态字段 DiClassStore.ServiceProvider = serviceProvider; DependencyResolver.SetResolver(mvcResolver); } } }
Global.asax
protected void Application_BeginRequest(object sender, EventArgs e) { HttpContext.Current.Items[typeof(IServiceScope)] = DiClassStore.ServiceProvider.CreateScope(); } protected void Application_EndRequest(object sender, EventArgs e) { IServiceScope scope = HttpContext.Current.Items[typeof(IServiceScope)] as IServiceScope; scope?.Dispose(); }
异常原因分析
- 静态字段被意外置空:
DiClassStore.ServiceProvider作为全局共享的静态字段,若有其他代码误操作修改该字段,会直接导致空引用。 - 应用域重启时机问题:IIS应用池回收、配置更新等场景会触发应用重启,若第一个请求在
Startup.Configuration初始化完成前到达,此时静态字段尚未赋值,调用CreateScope就会抛出异常。
修复方案
1. 增加空值检查与初始化校验
修改Global.asax的Application_BeginRequest方法,避免在容器未初始化时处理请求:
protected void Application_BeginRequest(object sender, EventArgs e) { if (DiClassStore.ServiceProvider == null) { HttpContext.Current.Response.StatusCode = 503; HttpContext.Current.Response.Write("服务初始化中,请稍后重试"); HttpContext.Current.Response.End(); return; } HttpContext.Current.Items[typeof(IServiceScope)] = DiClassStore.ServiceProvider.CreateScope(); }
2. 限制静态字段的赋值权限
修改DiClassStore类,确保服务提供器只能被初始化一次,防止意外修改:
public static class DiClassStore { private static IServiceProvider _serviceProvider; public static IServiceProvider ServiceProvider { get => _serviceProvider ?? throw new InvalidOperationException("DI容器未完成初始化"); set => _serviceProvider ??= value; // 仅允许首次赋值 } }
3. 改用Owin中间件管理请求作用域
替代Global.asax的事件处理,通过Owin中间件绑定服务作用域与请求生命周期,可靠性更高:
public void Configuration(IAppBuilder app) { ServiceCollection services = new ServiceCollection(); // 添加依赖项... IServiceProvider serviceProvider = services.BuildServiceProvider(); DiClassStore.ServiceProvider = serviceProvider; // 注册作用域管理中间件 app.Use(async (context, next) => { using (var scope = serviceProvider.CreateScope()) { context.Set(typeof(IServiceScope), scope); await next(); } }); DependencyResolver.SetResolver(mvcResolver); }
内容的提问来源于stack exchange,提问作者stefan
相关产品推荐
相关产品推荐

