2

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 并将其注入我的所有页面,那就是:

  • 捕获任何服务器请求中返回的 401(发布/获取等)
  • 尝试刷新令牌(为此调用 API)
  • 刷新失败返回登录

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

4

2 回答 2

3
  1. DelegatingHandler使用处理 401 响应代码创建自定义。
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.Httpnuget包。
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;
    }
}
于 2021-04-05T16:30:28.497 回答
2

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

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

于 2020-07-02T11:28:17.107 回答