You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AddSingleton注册依赖AuthenticationStateProvider的服务时触发异常

问题

我有一个依赖AuthenticationStateProvider的服务。当使用AddScoped注册该服务时运行正常,但改用AddSingleton注册后,在服务调用AuthenticationStateProvider的GetAuthenticationStateAsync方法时会抛出以下异常:

GetAuthenticationStateAsync was called before SetAuthenticationState.

我理解作用域的差异,但不清楚为何这会对AuthenticationStateProvider产生此类影响。

我的服务代码:

public class MyService : IMyService
{
    AuthenticationStateProvider _provider;
    public MyService(AuthenticationStateProvider provider)
    {
        _provider = provider;
    }

    public async Task<MyObject> DoThingsAsyc()
    {
        //Exception happens here
        var user = (await _provider.GetAuthenticationStateAsync()).User;
        ...
    }
}

Program.cs代码:

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IMyService, MyService>();
原因与解决方案
  • 核心原因:AuthenticationStateProvider本身是Scoped服务(Blazor默认注册方式),它的生命周期和当前请求/组件作用域绑定。当你把MyService注册为Singleton时,它会在应用启动时就被创建,此时注入的AuthenticationStateProvider属于启动时的根作用域,而不是后续每个用户会话的有效作用域,根本没机会被Blazor初始化(调用SetAuthenticationState),所以调用GetAuthenticationStateAsync会抛出异常。
  • Scoped服务正常的原因:当MyService是Scoped时,它会和每个请求/组件作用域一同创建,此时注入的AuthenticationStateProvider已经在当前作用域中被初始化完成,自然能正常调用GetAuthenticationStateAsync。
  • 解决方法:
    1. 优先保持MyService为Scoped注册,这是最贴合Blazor身份验证模型的方案,从根源避免生命周期不匹配问题。
    2. 如果必须使用Singleton,不要直接注入AuthenticationStateProvider,改为注入IServiceProvider,在需要调用时从当前有效作用域获取实例:
      public class MyService : IMyService
      {
          private readonly IServiceProvider _serviceProvider;
      
          public MyService(IServiceProvider serviceProvider)
          {
              _serviceProvider = serviceProvider;
          }
      
          public async Task<MyObject> DoThingsAsyc()
          {
              using var scope = _serviceProvider.CreateScope();
              var provider = scope.ServiceProvider.GetRequiredService<AuthenticationStateProvider>();
              var user = (await provider.GetAuthenticationStateAsync()).User;
              ...
          }
      }
      
      这样每次调用方法时,都会从当前有效的用户/请求作用域获取已初始化的AuthenticationStateProvider实例。

内容的提问来源于stack exchange,提问作者Jeremy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 16:58:13