Blazor Server端控制器Scoped依赖注入失效原因咨询
Blazor Server中Scoped服务在控制器注入失败的原因及解决方案
核心原因:两种Scoped生命周期的差异
Blazor Server的Scoped服务与传统ASP.NET MVC/Web API的Scoped服务生命周期边界完全不同:
- Blazor Server的Scoped服务绑定的是用户的SignalR连接(Blazor会话):从用户打开Blazor应用建立连接开始,到连接断开(比如关闭页面)结束,整个会话内共享同一个实例。
- MVC/Web API的Scoped服务绑定的是单个HTTP请求:每个请求创建一个新实例,请求完成后立即销毁。
你在program.cs中用AddScoped<MyClass>()注册的服务,默认是Blazor Server的会话级Scoped。当控制器处理HTTP请求时,它处于普通的HTTP请求上下文,无法访问Blazor会话的Scoped实例池,DI容器找不到对应的实例,所以注入返回null。
而Singleton服务是全局唯一的,不受上下文限制,任何请求或会话都能获取到实例,所以控制器注入正常。
解决方案:使用AddServerScoped实现跨上下文共享
如果你需要MyClass保持Blazor会话级的生命周期,同时让控制器也能注入到同一个实例,可以改用.NET 6+提供的AddServerScoped方法注册服务:
// program.cs中替换原来的AddScoped builder.Services.AddServerScoped<MyClass>();
AddServerScoped会将服务的生命周期与用户的Blazor SignalR连接绑定,同时通过Blazor Server的会话Cookie跟踪用户身份,让MVC控制器的HTTP请求能关联到对应的Blazor会话实例,从而实现跨组件和控制器的同实例注入。
补充说明
如果你的场景中,控制器不需要共享Blazor会话的MyClass实例,而是每个HTTP请求独立创建一个实例,可以单独为控制器注册Scoped服务,但这会导致Blazor组件和控制器使用不同的实例,不符合你“在Blazor生命周期内创建销毁”的需求,因此不推荐。
内容的提问来源于stack exchange,提问作者Mike T. Angelo
相关产品推荐
相关产品推荐

