.NET Blazor项目多差异化配置REST API客户端实现方案问询
多差异化配置REST API调用的Blazor实现方案
核心实现采用命名式HttpClient + 策略模式的组合方案,完全适配.NET官方推荐的IHttpClientFactory最佳实践,既实现了多客户端配置的完全隔离,又满足了可扩展、易维护的要求。
第一步:注册差异化命名HttpClient
在Program.cs(.NET 6+,Startup.cs逻辑一致)中为每个不同配置的API注册独立命名的HttpClient,避免全局配置污染:
var builder = WebApplication.CreateBuilder(args); // 注册自定义JWT处理程序,后续给授权客户端用 builder.Services.AddTransient<JwtAuthHandler>(); // 1. 注册需要跳过证书校验的API客户端 builder.Services.AddHttpClient("InsecureApiClient", client => { client.BaseAddress = new Uri("https://your-insecure-api-address.com/"); client.Timeout = TimeSpan.FromSeconds(30); }) .ConfigurePrimaryHttpMessageHandler(() => { return new HttpClientHandler { // 仅该客户端跳过证书校验,不会影响其他HTTP请求 ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true }; }); // 2. 注册支持带请求体GET的API客户端 builder.Services.AddHttpClient("CustomGetApiClient", client => { client.BaseAddress = new Uri("https://custom-get-api-address.com/"); }); // 3. 注册需要携带JWT认证的API客户端 builder.Services.AddHttpClient("JwtAuthApiClient", client => { client.BaseAddress = new Uri("https://jwt-protected-api-address.com/"); }) .AddHttpMessageHandler<JwtAuthHandler>();
注意:跳过证书校验存在安全风险,仅建议在内部测试环境或者完全可控的私有网络场景下使用,生产环境请配置合法的SSL证书。
JWT自动注入的消息处理程序示例:
public class JwtAuthHandler : DelegatingHandler { private readonly IAuthService _authService; // 你自己实现的认证服务,用于获取当前用户的JWT public JwtAuthHandler(IAuthService authService) { _authService = authService; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var token = await _authService.GetCurrentUserTokenAsync(); if (!string.IsNullOrEmpty(token)) { request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); } return await base.SendAsync(request, cancellationToken); } }
第二步:用策略模式封装API调用逻辑
定义统一的调用策略接口,每个API对应一个独立的策略实现,内部绑定对应命名的HttpClient:
定义公共策略接口
public interface IApiClientStrategy { Task<TResponse> SendAsync<TResponse>(string path, HttpMethod method, object payload = null, CancellationToken cancellationToken = default); }
各API独立策略实现
- 跳过证书校验的API策略:
public class InsecureApiClientStrategy : IApiClientStrategy { private readonly HttpClient _httpClient; public InsecureApiClientStrategy(IHttpClientFactory httpClientFactory) { _httpClient = httpClientFactory.CreateClient("InsecureApiClient"); } public async Task<TResponse> SendAsync<TResponse>(string path, HttpMethod method, object payload = null, CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(method, path); if (payload != null) request.Content = JsonContent.Create(payload); using var response = await _httpClient.SendAsync(request, cancellationToken); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync<TResponse>(cancellationToken: cancellationToken); } }
- 带请求体GET的API策略:
public class CustomGetApiClientStrategy : IApiClientStrategy { private readonly HttpClient _httpClient; public CustomGetApiClientStrategy(IHttpClientFactory httpClientFactory) { _httpClient = httpClientFactory.CreateClient("CustomGetApiClient"); } public async Task<TResponse> SendAsync<TResponse>(string path, HttpMethod method, object payload = null, CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(method, path); // 特殊处理带请求体的GET请求 if (payload != null) request.Content = JsonContent.Create(payload); using var response = await _httpClient.SendAsync(request, cancellationToken); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync<TResponse>(cancellationToken: cancellationToken); } }
- JWT认证的API策略:
public class JwtAuthApiClientStrategy : IApiClientStrategy { private readonly HttpClient _httpClient; public JwtAuthApiClientStrategy(IHttpClientFactory httpClientFactory) { _httpClient = httpClientFactory.CreateClient("JwtAuthApiClient"); } public async Task<TResponse> SendAsync<TResponse>(string path, HttpMethod method, object payload = null, CancellationToken cancellationToken = default) { using var request = new HttpRequestMessage(method, path); if (payload != null) request.Content = JsonContent.Create(payload); using var response = await _httpClient.SendAsync(request, cancellationToken); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync<TResponse>(cancellationToken: cancellationToken); } }
第三步:注册策略并实现上下文调用
将所有策略和调用上下文注册到DI容器,实现按需获取:
// 注册所有策略 builder.Services.AddSingleton<IApiClientStrategy, InsecureApiClientStrategy>(); builder.Services.AddSingleton<IApiClientStrategy, CustomGetApiClientStrategy>(); builder.Services.AddSingleton<IApiClientStrategy, JwtAuthApiClientStrategy>(); // 注册策略上下文,方便快速获取对应策略 public class ApiClientContext { private readonly IEnumerable<IApiClientStrategy> _strategies; public ApiClientContext(IEnumerable<IApiClientStrategy> strategies) { _strategies = strategies; } public IApiClientStrategy GetStrategy<TStrategy>() where TStrategy : IApiClientStrategy { return _strategies.OfType<TStrategy>().First(); } } builder.Services.AddSingleton<ApiClientContext>();
第四步:Blazor组件中使用
直接注入上下文按需调用即可:
@inject ApiClientContext ApiContext @code { // 调用跳过证书的API private async Task CallInsecureApi() { var client = ApiContext.GetStrategy<InsecureApiClientStrategy>(); var result = await client.SendAsync<DataModel>("api/data", HttpMethod.Get); } // 调用带请求体的GET接口 private async Task CallCustomGetApi() { var client = ApiContext.GetStrategy<CustomGetApiClientStrategy>(); var queryPayload = new { Page = 1, PageSize = 20, Keyword = "test" }; var result = await client.SendAsync<PageResult>("api/list", HttpMethod.Get, queryPayload); } // 调用JWT授权的API private async Task CallJwtAuthApi() { var client = ApiContext.GetStrategy<JwtAuthApiClientStrategy>(); var result = await client.SendAsync<UserInfo>("api/user/info", HttpMethod.Get); } }
方案优势
- 所有HttpClient配置完全隔离,修改单个API的配置不会影响其他请求,无全局配置污染
- 策略模式符合开闭原则,后续新增API仅需要添加新的策略实现即可,无需修改原有逻辑
- 基于IHttpClientFactory实现,自动管理HttpClient生命周期,规避端口耗尽、DNS更新不生效等常见问题
- 所有调用逻辑可单独单元测试,无硬编码耦合
内容的提问来源于stack exchange,提问作者Randy Marsh
相关产品推荐
相关产品推荐

