I'm developing a Blazor Server application that calls an external API. After successful login, I store the JWT token in ProtectedSessionStorage. While I can retrieve the token fine in Razor components, I get a JavaScript interop exception when trying to access it from a custom DelegatingHandler.
Error Details:
System.InvalidOperationException: 'JavaScript interop calls cannot beissued at this time. This is because the component is beingstatically rendered. When prerendering is enabled, JavaScript interopcalls can only be performed during the OnAfterRenderAsync lifecyclemethod.'
Service Registration:
builder.Services.AddScoped<ProtectedSessionStorage>();builder.Services.AddScoped<TokenService>();builder.Services.AddScoped<AuthTokenHandler>();builder.Services.AddHttpClient("AuthenticatedClient", client =>{ client.BaseAddress = new Uri(BaseUrl);}).AddHttpMessageHandler<AuthTokenHandler>();TokenService.cs
public class TokenService(ProtectedSessionStorage sessionStorage){ readonly string Key = "AccessToken"; public async Task SetAsync(string value) { try { await sessionStorage.SetAsync(Key, value); } catch { } } public async Task<string> GetAsync() { try { string result = string.Empty; var tokenResult = await sessionStorage.GetAsync<string>(Key); if (tokenResult.Success) { result = tokenResult.Value ?? string.Empty; } return result; } catch { return string.Empty; } }}AuthTokenHandler.cs
public class AuthTokenHandler(TokenService tokenService) : DelegatingHandler{ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var token = await tokenService.GetAsync();//exception occurs in this line if (!string.IsNullOrEmpty(token)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } return await base.SendAsync(request, cancellationToken); }}Razor Component
string token = await tokenService.GetAsync(); //this line can retrieve tokenvar httpClient = HttpClientFactory.CreateClient("AuthenticatedClient");var response = await httpClient.GetAsync(RelativeUrl);if (response.IsSuccessStatusCode){ message = "Authorized"; var result = await response.Content.ReadAsStringAsync();}else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized){ message = "Unauthorized";}