Blazor使用自定义组件时注入的IHttpContextAccessor在第二服务中为空问题
问题原因分析
- Blazor Server 生命周期特性导致上下文失效
Blazor Server 采用「初始HTTP请求 + 后续SignalR长连接」的混合运行模式:只有首次页面加载的请求阶段存在有效的HttpContext,页面渲染完成切换为SignalR连接后,原HTTP请求上下文会被框架释放,此时读取IHttpContextAccessor.HttpContext自然返回null。第一次调用服务时处于初始请求阶段可以正常读取,后续用户交互触发的服务调用运行在SignalR上下文中,就会出现上下文为null的问题。 - 服务注册冲突导致实例多次注入
你同时使用了services.AddScoped<IEmployeeServices,EmployeeServices>()和services.AddHttpClient<IEmployeeServices,EmployeeServices>()注册同一服务接口:AddHttpClient默认会将注册的服务设置为Transient生命周期,和你手动指定的Scoped生命周期冲突,DI容器在解析时会生成多个实例,所以会出现构造函数多次执行的现象。 - 自定义组件属性实现冗余易出错
你手动维护字典实现的属性透传功能,Blazor原生已经提供了@attributes语法支持attribute splatting,不需要手动绑定每一个HTML属性,直接在元素上写@attributes="InputParameters"即可完成任意属性的透传,你当前代码中还出现了size="@InputParameters["min"]"的绑定错误,可能引发额外的参数异常。
解决方案
- 移除对
IHttpContextAccessor的直接依赖:如果需要使用HttpContext中的数据,在组件的OnInitializedAsync生命周期方法(此时HttpContext还未释放)中提前读取需要的字段,存入自定义的Scoped生命周期状态服务中,后续所有业务服务都从该状态服务读取需要的上下文信息。 - 修复服务注册冲突:要么删除手动添加的
services.AddScoped<IEmployeeServices,EmployeeServices>()注册,保留HttpClient的注册逻辑;要么调整HttpClient注册方式为services.AddHttpClient<EmployeeServices>(),在Scoped注册中通过服务提供者工厂获取HttpClient实例,保证同一作用域内只有一份服务实例。 - 优化自定义组件属性透传逻辑:替换手动绑定的属性为原生
@attributes语法,简化代码同时避免绑定错误。
内容的提问来源于stack exchange,提问作者PontiacGTX
相关产品推荐
相关产品推荐

