Blazor WASM - Global Catch 401 并导航到所有 HttpClient 调用的登录页面

Blazor WASM - Global Catch 401 and navigate to login page on all HttpClient calls

blazor template httpclient中添加在Program.cs class中:

builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

以后使用如下:

forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");

有什么方法可以重写该基础 httpclient 并将其注入我的所有页面,这将:

我看到我可以定义一个自定义服务来包装所有这些 HTTP 客户端调用并执行我提到的操作,但是有没有更好的方法来做到这一点?

如果您想通过 HttpClient 拦截所有调用,那么您需要创建一个允许您进行 HttpCalls 的服务,这样您就可以在其中拦截它们并使用 HttpClient。

PS:您应该将任何实现 IDisposable 的 class(例如 HttpClient)的注册从 Transient 更改为 Scoped。这将在未来的 Blazor 模板中改变。

  1. 使用处理 401 响应代码创建自定义 DelegatingHandler
public class CustomMessageHandler : DelegatingHandler
{
    private readonly string host;
    readonly NavigationManager _navigationManager;

    CustomMessageHandler(IWebAssemblyHostEnvironment webAssemblyHostEnvironment, navigationManager)
    {
        host = webAssemblyHostEnvironment.BaseAddress;
        _navigationManager = navigationManager;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        {
            Console.WriteLine("CustomMessageHandler catch 401");

            // TODO: some logic (e.g. refreshing token)
            
            // Or just redirect to login page.
            string loingUrl = "http://some-site/login";
            _navigationManager.NavigateTo(loingUrl, forceLoad: true);
        }

        return response;
    }
}
  1. IServiceCollection 中注册创建 CustomMessageHandler(在 blazor.Client 项目中)
builder.Services.AddScoped<CustomMessageHandler>();
  1. 同时使用我们的 CustomMessageHandler 注册已配置的 httpClient(在 blazor.Client 项目中)。 .AddHttpClient 需要 Microsoft.Extensions.Http nuget 包。
builder.Services.AddHttpClient("BlazorServerHttpClient", 
    client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
        .AddHttpMessageHandler<CustomMessageHandler>();
  1. 从 blazor.Client 到 blazor.Server 的所有 httpClient 请求都必须像这样使用 IHttpClientFactory:
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

public class WeatherService
{
    private readonly IHttpClientFactory _clientFactory;

    public WeatherService(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task<WeatherForecast[]> GetWeatherForecast()
    {
        var client = _clientFactory.CreateClient("BlazorServerHttpClient");
        WeatherForecast[] result = await client.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");

        return result;
    }
}