宿州做企业网站公司,wordpress哪里编辑页脚,凡科互动怎么发布,正邦设计广州分公司使用自定义DelegatingHandler编写更整洁的Typed HttpClient简介#xfeff;我写了很多HttpClient[1]#xff0c;包括类型化的客户端。自从我发现Refit[2]以来#xff0c;我只使用了那一个#xff0c;所以我只编写了很少的代码#xff01;但是我想到了你#xff01;你们中… 使用自定义DelegatingHandler编写更整洁的Typed HttpClient简介我写了很多HttpClient[1]包括类型化的客户端。自从我发现Refit[2]以来我只使用了那一个所以我只编写了很少的代码但是我想到了你你们中的某些人不一定会使用Refit[3]因此我将为您提供一些技巧以使用HttpClient消息处理程序[4]尤其是DelegatingHandlers[5]编写具有最大可重用性的类型化HttpClient[6]。编写类型化的HttpClient来转发JWT并记录错误这是要整理的HttpClient[7]using DemoRefit.Models;
using DemoRefit.Repositories;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;namespace DemoRefit.HttpClients
{public class CountryRepositoryClient : ICountryRepositoryClient{private readonly HttpClient _client;private readonly IHttpContextAccessor _httpContextAccessor;private readonly ILoggerCountryRepositoryClient _logger;public CountryRepositoryClient(HttpClient client, ILoggerCountryRepositoryClient logger, IHttpContextAccessor httpContextAccessor){_client  client;_logger  logger;_httpContextAccessor  httpContextAccessor;}public async TaskIEnumerableCountry GetAsync(){try{string accessToken  await _httpContextAccessor.HttpContext.GetTokenAsync(access_token);if (string.IsNullOrEmpty(accessToken)){throw new Exception(Access token is missing);}_client.DefaultRequestHeaders.Authorization  new AuthenticationHeaderValue(bearer, accessToken);var headers  _httpContextAccessor.HttpContext.Request.Headers;if (headers.ContainsKey(X-Correlation-ID)  !string.IsNullOrEmpty(headers[X-Correlation-ID])){_client.DefaultRequestHeaders.Add(X-Correlation-ID, headers[X-Correlation-ID].ToString());}using (HttpResponseMessage response  await _client.GetAsync(/api/democrud)){response.EnsureSuccessStatusCode();return await response.Content.ReadAsAsyncIEnumerableCountry();}}catch (Exception e){_logger.LogError(e, Failed to run http query);return null;}}}
}
这里有许多事情需要清理因为它们在您将在同一应用程序中编写的每个客户端中可能都是多余的•从HttpContext读取访问令牌•令牌为空时管理访问令牌•将访问令牌附加到HttpClient[8]进行委派•从HttpContext读取CorrelationId•将CorrelationId附加到HttpClient[9]进行委托•使用EnsureSuccessStatusCode验证Http查询是否成功编写自定义的DelegatingHandler来处理冗余代码这是DelegatingHandler[10]using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;namespace DemoRefit.Handlers
{public class MyDelegatingHandler : DelegatingHandler{private readonly IHttpContextAccessor _httpContextAccessor;private readonly ILoggerMyDelegatingHandler _logger;public MyDelegatingHandler(IHttpContextAccessor httpContextAccessor, ILoggerMyDelegatingHandler logger){_httpContextAccessor  httpContextAccessor;_logger  logger;}protected override async TaskHttpResponseMessage SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){HttpResponseMessage httpResponseMessage;try{string accessToken  await _httpContextAccessor.HttpContext.GetTokenAsync(access_token);if (string.IsNullOrEmpty(accessToken)){throw new Exception($Access token is missing for the request {request.RequestUri});}request.Headers.Authorization  new AuthenticationHeaderValue(bearer, accessToken);var headers  _httpContextAccessor.HttpContext.Request.Headers;if (headers.ContainsKey(X-Correlation-ID)  !string.IsNullOrEmpty(headers[X-Correlation-ID])){request.Headers.Add(X-Correlation-ID, headers[X-Correlation-ID].ToString());}httpResponseMessage  await base.SendAsync(request, cancellationToken);httpResponseMessage.EnsureSuccessStatusCode();}catch (Exception ex){_logger.LogError(ex, Failed to run http query {RequestUri}, request.RequestUri);throw;}return httpResponseMessage;}}
}
如您所见现在它封装了用于同一应用程序中每个HttpClient[11]的冗余逻辑 。现在清理后的HttpClient[12]如下所示using DemoRefit.Models;
using DemoRefit.Repositories;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;namespace DemoRefit.HttpClients
{public class CountryRepositoryClientV2 : ICountryRepositoryClient{private readonly HttpClient _client;private readonly ILoggerCountryRepositoryClient _logger;public CountryRepositoryClientV2(HttpClient client, ILoggerCountryRepositoryClient logger){_client  client;_logger  logger;}public async TaskIEnumerableCountry GetAsync(){using (HttpResponseMessage response  await _client.GetAsync(/api/democrud)){try{return await response.Content.ReadAsAsyncIEnumerableCountry();}catch (Exception e){_logger.LogError(e, Failed to read content);return null;}}}}
}
好多了不是吗????最后让我们将DelegatingHandler[13]附加到Startup.cs中的HttpClient[14]using DemoRefit.Handlers;
using DemoRefit.HttpClients;
using DemoRefit.Repositories;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Refit;
using System;namespace DemoRefit
{public class Startup{public Startup(IConfiguration configuration){Configuration  configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddHttpContextAccessor();services.AddControllers();services.AddHttpClientICountryRepositoryClient, CountryRepositoryClientV2().ConfigureHttpClient(c  c.BaseAddress  new Uri(Configuration.GetSection(Apis:CountryApi:Url).Value)).AddHttpMessageHandlerMyDelegatingHandler();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseHttpsRedirection();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints {endpoints.MapControllers();});}}
}
使用Refit如果您正在使用Refit[15]则绝对可以重用该DelegatingHandler[16]例using DemoRefit.Handlers;
using DemoRefit.HttpClients;
using DemoRefit.Repositories;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Refit;
using System;namespace DemoRefit
{public class Startup{public Startup(IConfiguration configuration){Configuration  configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddHttpContextAccessor();services.AddControllers();services.AddRefitClientICountryRepositoryClient().ConfigureHttpClient(c  c.BaseAddress  new Uri(Configuration.GetSection(Apis:CountryApi:Url).Value));.AddHttpMessageHandlerMyDelegatingHandler();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseHttpsRedirection();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints {endpoints.MapControllers();});}}
}
轮子介绍Refit是一个深受Square的 Retrofit 库启发的库,目前在github上共有star 4000枚通过这个框架可以把你的REST API变成了一个活的接口:public interface IGitHubApi
{[Get(/users/{user})]TaskUser GetUser(string user);
}
RestService类生成一个IGitHubApi的实现它使用HttpClient进行调用:var gitHubApi  RestService.ForIGitHubApi(https://api.github.com);var octocat  await gitHubApi.GetUser(octocat);
查看更多https://reactiveui.github.io/refit/References[1] HttpClient: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?viewnetcore-3.0[2] Refit: https://github.com/reactiveui/refit[3] Refit: https://github.com/reactiveui/refit[4] HttpClient消息处理程序: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/httpclient-message-handlers[5] DelegatingHandlers: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?viewnetframework-4.8[6] 类型化HttpClient: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests[7] 键入的HttpClient: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests[8] HttpClient: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?viewnetcore-3.0[9] HttpClient: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?viewnetcore-3.0[10] DelegatingHandler: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?viewnetframework-4.8[11] HttpClient: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?viewnetcore-3.0[12] HttpClient: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?viewnetcore-3.0[13] DelegatingHandler: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?viewnetframework-4.8[14] HttpClient: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?viewnetcore-3.0[15] Refit: https://github.com/reactiveui/refit[16] DelegatingHandler: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?viewnetframework-4.8