我有一个键入的客户端,我想将其注册为单例:
public class SomeHttpClient
{
private readonly IHttpClientFactory _clientFactory;
public SomeHttpClient(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public Task MakeSomeCallAsync(...)
{
var client = _clientFactory.Create();
// Do more stuff
}
}
Run Code Online (Sandbox Code Playgroud)
类型化的客户端必须是单例的,因为它有一些断路器逻辑,如果 API 对客户端进行速率限制,则会中断电路。电路必须在整个应用程序中断开,显然不仅仅是当前的请求管道(否则客户端将继续访问已经从其他实例进行速率限制的 API)。这已经通过使用封装了该功能的类型化客户端(虽然不是 Polly)来实现的。
现在因为类型化的客户端将是一个单身人士,我们不能注入一个单身人士,HttpClient
因为这会带来我们以前在一个 long living 中遇到的所有问题HttpClient
。显而易见的解决方案是注入一个HttpClientFactory
现在可以用来在HttpClient
每次键入的客户端需要一个实例时发出一个实例而不必担心生命周期管理等,因为这已经推迟到HttpClientFactory
现在。
我现在的问题是如何HttpClientFactory
为一个简单的功能集成测试创建默认值,我想在其中实例化一个类型化的客户端,看看我是否可以点击 API 并从自动化测试中获得成功的响应?
我不想设置一个 ASP.NET Core TestServer 和一个围绕它的整个应用程序,因为这对于我现在想要做的那种功能测试来说太过分了。
没有可用于注入HttpClientFactory
?
c# dotnet-httpclient .net-core asp.net-core httpclientfactory
以下两种设置 HttpClient 的场景有什么区别吗?
我应该选择其中一种而不是另一种吗?
键入的客户端:
public class CatalogService
{
private readonly HttpClient _httpClient;
public CatalogService(HttpClient httpClient) {
_httpClient = httpClient;
}
public async Task<string> Get() {
var response = await _httpClient.GetAsync();
....
}
public async Task Post() {
var response = await _httpClient.PostAsync();
...
}
}
// Startup.cs
//Add http client services at ConfigureServices(IServiceCollection services)
services.AddHttpClient<ICatalogService, CatalogService>();
Run Code Online (Sandbox Code Playgroud)
IHttpClientFactory:
public class CatalogService
{
private readonly IHttpClientFactory _factory;
public CatalogService(IHttpClientFactory factory) {
_factory = factory;
}
public async Task<string> Get() {
var …
Run Code Online (Sandbox Code Playgroud) c# async-await dotnet-httpclient asp.net-core httpclientfactory
我想使用HttpClientFactory
.NET Core 2.1中提供的那个,但我也想在创建时使用它HttpClientHandler
来利用AutomaticDecompression
属性HttpClients
.
我很努力,因为.AddHttpMessageHandler<>
需要一个DelegatingHandler
不是HttpClientHandler
.
有谁知道如何让这个工作?
谢谢,吉姆
c# dotnet-httpclient .net-core httpclientfactory .net-core-2.1
有没有办法向 IHttpClientFactory 创建的所有客户端添加处理程序?我知道您可以对指定客户执行以下操作:
services.AddHttpClient("named", c =>
{
c.BaseAddress = new Uri("TODO");
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue
{
NoCache = true,
NoStore = true,
MaxAge = new TimeSpan(0),
MustRevalidate = true
};
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
});
Run Code Online (Sandbox Code Playgroud)
但我不想使用命名客户端,我只想向通过以下方式返回给我的所有客户端添加一个处理程序:
clientFactory.CreateClient();
Run Code Online (Sandbox Code Playgroud) 在我的 .net core Web api 项目中,我想使用外部 API,以便获得预期的响应。
我注册和使用 HttpClient 的方式如下。在启动中,我添加了以下代码,称为命名类型 httpclient 方式。
services.AddHttpClient<IRecipeService, RecipeService>(c => {
c.BaseAddress = new Uri("https://sooome-api-endpoint.com");
c.DefaultRequestHeaders.Add("x-raay-key", "123567890754545645gggg");
c.DefaultRequestHeaders.Add("x-raay-host", "sooome-api-endpoint.com");
});
Run Code Online (Sandbox Code Playgroud)
除此之外,我还有 1 个服务,我在其中注入了 HttpClient。
public class RecipeService : IRecipeService
{
private readonly HttpClient _httpClient;
public RecipeService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<List<Core.Dtos.Recipes>> GetReBasedOnIngAsync(string endpoint)
{
using (var response = await _httpClient.GetAsync(recipeEndpoint))
{
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
创建 httpClient 时,如果我将鼠标悬停在对象本身上,则基本 URI/标头会丢失,并且我不明白为什么会发生这种情况。如果有人能透露一些信息,我将不胜感激:)
第一次更新
该服务正在如下所示的控制器之一中使用。该服务由 DI 注入,然后将相对路径解析为该服务(我假设我已经将基本 URL 存储在客户端中)也许我做错了?
namespace ABC.Controllers
{
[ApiController]
[Route("[controller]")] …
Run Code Online (Sandbox Code Playgroud) c# asp.net-web-api dotnet-httpclient asp.net-core-webapi httpclientfactory
所以,我在Startup.cs中注册了一个带有服务集合的命名客户端:
services.AddHttpClient(someServiceName,
client => client.BaseAddress = baseAddress);
Run Code Online (Sandbox Code Playgroud)
现在可以IHttpClientFactory
从我的服务提供商那里注入一个.
使用它IHttpClientFactory
,我想出了一个客户端实例:
var client = httpClientFactory.CreateClient(someServiceName)
Run Code Online (Sandbox Code Playgroud)
曾几何时,有必要非常小心处理HttpClient
实例,因为它很少是正确的事情.
但是,现在我们已经HttpClientFactory
,重要了吗?应该/可以client
不必担心吗?例如
using (var httpClient = httpClientFactory.CreateClient(someServiceName))
using (var response = await httpClient.PostAsync(somePath, someData))
{
var content = await response.Content.ReadAsAsync<SomeResponse>();
//...
}
Run Code Online (Sandbox Code Playgroud) idisposable dotnet-httpclient .net-core asp.net-core-2.1 httpclientfactory
这个答案展示了如何向 HttpClient 请求添加 cookie。但其中一条评论警告说,该内容CookieContainer
已缓存在 HttpClient 上。我的大部分 cookie 不应再次发送给其他用户。
我希望能够清除池中 HttpClient 实例中添加的HttpClientFactory
内容。CookieContainer
HttpClient
如果我通过电话得到我的,httpClientFactory.CreateClient
是否有可能我收到的邮件CookieContainer
上有以前的内容?
更新:
我的问题的答案是肯定的! CookieContainer
适用于当您想在每次调用时发送相同的 cookie 时。
如果您需要在每次调用时发送不同的 cookie,有多种方法可以实现。但最简单的方法是将其放在标题中。
因为客户端的每个请求HttpClientFactory
都会创建一个新的HttpClient
,所以您可以添加到客户端的标头中,而不必担心它会重用 cookie。
做到这一点的关键是设置UseCookies
。它必须设置为 false,否则您添加到标头的 cookie 将被忽略。完成此操作后,您可以将 Cookie 添加到标题中的“Cookies”键下,并将它们作为分号分隔的键值对(之间用等号)输入。您的 cookie 将返回到“Set-Cookies”标题中。
使用ASP.NET Core 2.1中的新HttpClientFactory,可以很容易地使用基本URL,默认标题等配置自定义HTTP客户端.
但是,我还没有找到一种方法来集中配置,让我从当前请求上下文中注入头文件.例如,考虑使用Authorization
标头调用的服务,我希望将其传递给所有底层服务.能够在类中的.AddHttpClient()
调用中配置它会很棒,但我无法弄清楚如何从那里获取请求上下文.services
Startup
有任何想法吗?
.NET Core 2.1带有一个称为的新工厂HttpClientFactory
,但是我不知道如何模拟它来对包含REST服务调用的某些方法进行单元测试。
正在使用.NET Core IoC容器注入工厂,该方法的作用是从工厂创建一个新客户端:
var client = _httpClientFactory.CreateClient();
Run Code Online (Sandbox Code Playgroud)
然后使用客户端从REST服务获取数据:
var result = await client.GetStringAsync(url);
Run Code Online (Sandbox Code Playgroud) 我想为 Typed HttpClient 添加一个 HttClientHandler 以包含证书身份验证。
我在网上找到的所有例子都是这样的:
services.AddHttpClient<IMyService, MyService>()
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new HttpClientHandler()
{
// Set here whatever you need to get configured
};
});
Run Code Online (Sandbox Code Playgroud)
但是我不想在此处包含获取证书的所有逻辑,因此我想使用ConfigurePrimaryHttpMessageHandler<>的通用版本并编写自己的消息处理程序以在请求中包含证书。
问题是我很难理解我应该如何实现消息处理程序......我应该从HttpClientHandler继承吗?
请帮忙!
更新
正如我最初怀疑的那样,@Nkosi 证实,从 HttpClient 处理程序派生是这种情况下的方法。最后的代码类似于:
public class MyHttpClientHandler : HttpClientHandler
{
private readonly IMyConfiguration _myConfiguration;
public MyHttpClientHandler(IMyConfiguration myConfiguration)
{
_myConfiguration = myConfiguration;
using (var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(
X509FindType.FindBySerialNumber,
_myConfiguration.MyCertificateSerial,
true);
X509Certificate2 certificate = certCollection[0];
ClientCertificateOptions = ClientCertificateOption.Manual;
SslProtocols …
Run Code Online (Sandbox Code Playgroud) c# dotnet-httpclient .net-core httpclientfactory .net-core-2.1