如何正确地将 HttpClient DI 成 FlurlClient?
How to correctly DI HttpClient into FlurlClient?
注册自定义消息处理程序似乎不适用于 FlurlClient。
.. other setup logic
/// <summary>
/// Configures the application services.
/// </summary>
/// <param name="services">The service collection.</param>
public override void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ConsoleCorrelationIdHandler>();
this.AddHttpClient<ICatalogService, CatalogService>(services, "http://httpbin.org");
}
private void AddHttpClient<TClient, TImplementation>(IServiceCollection services, string url = null)
where TClient : class
where TImplementation : class, TClient
=> services.AddHttpClient<TClient, TImplementation>(client =>
{
if (!string.IsNullOrWhiteSpace(url))
client.BaseAddress = new Uri(url);
})
.AddHttpMessageHandler<ConsoleCorrelationIdHandler>(); // Appends CorrelationId to all outgoing HTTP requests.
在这里,我使用 ConsoleCorrelationIdHandler 注册了一个新的 HttpClient,它向所有传出请求添加了一个关联 ID header。
public class CatalogService : ICatalogService
{
private readonly IFlurlClient _httpClient;
public CatalogService(HttpClient httpClient)
{
_httpClient = new FlurlClient(httpClient);
}
public async Task GetSomething()
{
var x = await this._httpClient.BaseUrl
.AppendPathSegment("get")
.GetJsonAsync();
Console.WriteLine(JsonConvert.SerializeObject(x)); // Doesnt have CorrelationId header, which should have been added by handler.
}
}
现在,当调用 GetSomething 时,IFlurlClient 确实具有已注册 httpclient 的基础 url,但不会调用消息处理程序。
让我们分解你的流利调用,看看发生了什么:
_httpClient.BaseUrl
您现在有一个字符串的引用。您在这里丢失了对客户的引用。
.AppendPathSegment("get")
此处调用的是创建 Flurl.Url
对象并将 get
附加到路径的字符串扩展方法。
.GetJsonAsync();
此处您在 Url
上调用一个扩展方法,它创建一个 FlurlRequest
并调用它的 GetJsonAsync
方法。由于没有对您要使用的客户端的引用,它将使用已注册的 FlurlClientFactory 寻找一个客户端。在那里找不到,它会创建一个新的。
简而言之,您在调用开始时丢失了对 FlurlClient
的引用。
修复方法如下:
var x = await this._httpClient
.Request("get")
.GetJsonAsync();
注册自定义消息处理程序似乎不适用于 FlurlClient。
.. other setup logic
/// <summary>
/// Configures the application services.
/// </summary>
/// <param name="services">The service collection.</param>
public override void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ConsoleCorrelationIdHandler>();
this.AddHttpClient<ICatalogService, CatalogService>(services, "http://httpbin.org");
}
private void AddHttpClient<TClient, TImplementation>(IServiceCollection services, string url = null)
where TClient : class
where TImplementation : class, TClient
=> services.AddHttpClient<TClient, TImplementation>(client =>
{
if (!string.IsNullOrWhiteSpace(url))
client.BaseAddress = new Uri(url);
})
.AddHttpMessageHandler<ConsoleCorrelationIdHandler>(); // Appends CorrelationId to all outgoing HTTP requests.
在这里,我使用 ConsoleCorrelationIdHandler 注册了一个新的 HttpClient,它向所有传出请求添加了一个关联 ID header。
public class CatalogService : ICatalogService
{
private readonly IFlurlClient _httpClient;
public CatalogService(HttpClient httpClient)
{
_httpClient = new FlurlClient(httpClient);
}
public async Task GetSomething()
{
var x = await this._httpClient.BaseUrl
.AppendPathSegment("get")
.GetJsonAsync();
Console.WriteLine(JsonConvert.SerializeObject(x)); // Doesnt have CorrelationId header, which should have been added by handler.
}
}
现在,当调用 GetSomething 时,IFlurlClient 确实具有已注册 httpclient 的基础 url,但不会调用消息处理程序。
让我们分解你的流利调用,看看发生了什么:
_httpClient.BaseUrl
您现在有一个字符串的引用。您在这里丢失了对客户的引用。
.AppendPathSegment("get")
此处调用的是创建 Flurl.Url
对象并将 get
附加到路径的字符串扩展方法。
.GetJsonAsync();
此处您在 Url
上调用一个扩展方法,它创建一个 FlurlRequest
并调用它的 GetJsonAsync
方法。由于没有对您要使用的客户端的引用,它将使用已注册的 FlurlClientFactory 寻找一个客户端。在那里找不到,它会创建一个新的。
简而言之,您在调用开始时丢失了对 FlurlClient
的引用。
修复方法如下:
var x = await this._httpClient
.Request("get")
.GetJsonAsync();