无效操作异常:在使用ProtectedLocalStorage的 Blazor Server中,此时无法发出JavaScript互操作调用

前端开发 2026-07-12

我正在构建一个Blazor Server (.NET 10.0) 应用,使用JWT验证。 我在客户端使用 ProtectedLocalStorage 来持久化JWT令牌,使用自定义 AuthenticationStateProvider 来解码并暴露声明。

我在页面加载时或尝试登出时遇到这个错误,因为登出控制器需要授权,因此需要带有Bearer令牌,但由于这个错误我无法获取它:

InvalidOperationException: JavaScript interop calls cannot be issued at this time.
This is because the component is being statically rendered. When prerendering is
enabled, JavaScript interop calls can only be performed during the
OnAfterRenderAsync lifecycle method.

设置

TokenProvider.cs

public class TokenProvider
{
    private const string TokenKey = "authToken";
    private readonly ProtectedLocalStorage _storage;

    public TokenProvider(ProtectedLocalStorage storage) => _storage = storage;

    public async Task<string?> GetTokenAsync()
    {
        try
        {
            var result = await _storage.GetAsync<string>(TokenKey);
            return result.Success ? result.Value : null;
        }
        catch (Exception ex)           //Getting exception hit here
        {
            Console.WriteLine($"GetTokenAsync failed: {ex.GetType().Name} - {ex.Message}");
            return null;
        }
    }
}

AuthStateProvider.cs

public class AuthStateProvider : AuthenticationStateProvider
{
    private readonly TokenProvider _tokenService;

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var token = await _tokenService.GetTokenAsync(); // ← triggers JS interop
        if (string.IsNullOrWhiteSpace(token))
            return Unauthenticated();

        var handler = new JwtSecurityTokenHandler();
        var jwt = handler.ReadJwtToken(token);
        var identity = new ClaimsIdentity(jwt.Claims, "jwt");
        return new AuthenticationState(new ClaimsPrincipal(identity));
    }
}

Home.razor

@page "/"
@attribute [Authorize]

App.razor:

<Routes @rendermode="InteractiveServer" />
  • 使用 new InteractiveServerRenderMode(prerender: false) 禁用预渲染(prerendering)- 这不工作。

我没有使用任何 OnInitializedOnInitializedAsync,但仍然遇到这个错误。我也在中间件中添加了提供程序。请帮我解决。

任何完整可运行的示例都将不胜感激。

解决方案

我认为这不是标准设计,因为JWT是用于客户端-服务器应用的。当你在Blazor Server中使用JWT时,客户端或页面是由服务器渲染的(类似ASP.NET WebForms),编译后的页面再发送给客户端。如果你想访问JsRuntime、localStorage或 cookies,你需要使用OnAfterRender。

不管怎样,要想解决这个问题,在GetTokenAsync() 内添加try-catch,并且不要在catch中写任何处理代码。

try
{
    //your code
}
catch (Exception) { }

服务器端第一次发生错误(你忽略了它),浏览器端第二次就能正常工作。
当你在Blazor Server使用预渲染时,所有事件都会发生两次,第一次在服务器端,第二次在浏览器端。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章