最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Blazor Server: Unable to access ProtectedSessionStorage value from HttpMessageHandler - Stack Overflow

programmeradmin0浏览0评论

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 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.'

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 token
var 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";
}

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 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.'

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 token
var 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";
}
Share Improve this question asked yesterday Anuj KarkiAnuj Karki 6176 silver badges29 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

You could try create a CustomHttpClientFactory instead of using DelegatingHandler to pass token parameter when creating httpclient.

    public class CustomHttpClientFactory(HttpClient client)
    {
        public HttpClient CreateClient(string? token)
        {
            if (!string.IsNullOrEmpty(token))
            {
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            }
            //client.BaseAddress = new Uri(BaseUrl);
            return client;
        }
    }
builder.Services.AddScoped<CustomHttpClientFactory>();
builder.Services.AddHttpClient<CustomHttpClientFactory>();

Then use directly

@inject CustomHttpClientFactory HttpClientFactory
...
string token = await tokenService.GetAsync();
var httpClient = HttpClientFactory.CreateClient(token);
发布评论

评论列表(0)

  1. 暂无评论