C# 将HttpClientFactory配置为使用当前请求上下文中的数据
有了ASP.NET Core 2.1中的新功能,使用基本URL、默认标题等配置自定义HTTP客户机非常容易 然而,我还没有找到一种集中配置的方法,使我能够从当前请求上下文中注入头。例如,考虑调用一个名为<代码>授权> /COD>标头的服务,我希望将其传递给所有底层服务。如果能够在C# 将HttpClientFactory配置为使用当前请求上下文中的数据,c#,asp.net-core-2.1,httpclientfactory,C#,Asp.net Core 2.1,Httpclientfactory,有了ASP.NET Core 2.1中的新功能,使用基本URL、默认标题等配置自定义HTTP客户机非常容易 然而,我还没有找到一种集中配置的方法,使我能够从当前请求上下文中注入头。例如,考虑调用一个名为授权> /COD>标头的服务,我希望将其传递给所有底层服务。如果能够在启动类中的服务上的.AddHttpClient()调用中配置它,那就太棒了,但是我不知道如何从那里获取请求上下文 有什么想法吗?研究这个答案会让我找到多个答案。我认为第一种方法是你正在寻找的,第二种方法是一个很好的选择 为了配置
启动
类中的服务
上的.AddHttpClient()
调用中配置它,那就太棒了,但是我不知道如何从那里获取请求上下文
有什么想法吗?研究这个答案会让我找到多个答案。我认为第一种方法是你正在寻找的,第二种方法是一个很好的选择 为了配置多个客户端,您可以使用。这些客户端被注册为临时客户端。使用DI获取可以访问请求上下文的服务 为此,我们需要IHttpContextAccessor。在这种情况下,您不必自己注册,因为Identity已经为您注册了 否则,在启动中添加以下行: 接下来,我们可以配置命名客户端“github”: 创建一个类型化客户端。我添加了两个选项来添加设置。一个通过请求上下文,另一个通过单例类:
public class GitHubService
{
public HttpClient Client { get; }
public GitHubService(HttpClient client, HttpClientSettings httpClientSettings, IHttpContextAccessor httpContextAccessor)
{
var bearerToken = httpContextAccessor.HttpContext.Request
.Headers["Authorization"]
.FirstOrDefault(h => h.StartsWith("bearer ", StringComparison.InvariantCultureIgnoreCase));
// Add authorization if found
if (bearerToken != null)
client.DefaultRequestHeaders.Add("Authorization", bearerToken);
// Or the value from httpClientSettings:
client.DefaultRequestHeaders.Add("Authorization", httpClientSettings.BearerToken);
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); // GitHub API versioning
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); // GitHub requires a user-agent
Client = client;
}
}
注册客户端:
// The typed client is registered as transient with DI.
services.AddHttpClient<GitHubService>();
您可以这样使用客户端:
public class MyController : ControllerBase
{
private readonly IHttpClientFactory _clientFactory;
public MyController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task<ActionResult> StartCall()
{
var client = _clientFactory.CreateClient("github");
var response = await client.GetAsync("/repos/aspnet/docs/issues");
}
}
public class MyController : ControllerBase
{
private readonly GitHubService _gitHubService;
public MyController(GitHubService gitHubService)
{
_gitHubService = gitHubService;
}
public async Task<ActionResult> StartCall()
{
var response = await _gitHubService.Client.GetAsync("/repos/aspnet/docs/issues");
}
}
公共类MyController:ControllerBase
{
私有只读GitHubService\u GitHubService;
公共MyController(GitHubService GitHubService)
{
_gitHubService=gitHubService;
}
公共异步任务StartCall()
{
var response=wait_gitHubService.Client.GetAsync(“/repos/aspnet/docs/issues”);
}
}
您的思路是正确的,但是缺少对当前请求上下文的访问,这就是我认为OP WANTS的原因。我的示例假设令牌在某个地方从请求上下文复制到HttpClientSettings。@RuardvanElburg…这就是我正在解决的问题的一半。如果您能扩展您的答案,并概述一个实现这一点的好方法,那将是非常好的:)@TomasLycken我想知道,这个答案对您有帮助吗?还是仍然缺少什么?我想添加services.BuildServiceProvider()
在每次调用时创建一个新的“服务池”。因此,在AddHttpClient方法中使用此服务提供程序获得的单例服务将与应用程序其余部分中获得的服务不同。在这种情况下,您将在AddHttpClient方法中获得“正确”的服务提供商作为参数,如下所示:services.AddHttpClient(“github”,(serviceProvider,c)=>
。介意我借用一些您的内容用于我自己的帖子,并将其更改为专门围绕cookies集合吗?顺便说一句,这是个好问题。
public class GitHubService
{
public HttpClient Client { get; }
public GitHubService(HttpClient client, HttpClientSettings httpClientSettings, IHttpContextAccessor httpContextAccessor)
{
var bearerToken = httpContextAccessor.HttpContext.Request
.Headers["Authorization"]
.FirstOrDefault(h => h.StartsWith("bearer ", StringComparison.InvariantCultureIgnoreCase));
// Add authorization if found
if (bearerToken != null)
client.DefaultRequestHeaders.Add("Authorization", bearerToken);
// Or the value from httpClientSettings:
client.DefaultRequestHeaders.Add("Authorization", httpClientSettings.BearerToken);
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); // GitHub API versioning
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); // GitHub requires a user-agent
Client = client;
}
}
// The typed client is registered as transient with DI.
services.AddHttpClient<GitHubService>();
services.AddSingleton<HttpClientSettings>();
public class HttpClientSettings
{
public string BearerToken { get; set; }
}
public class MyController : ControllerBase
{
private readonly GitHubService _gitHubService;
public MyController(GitHubService gitHubService)
{
_gitHubService = gitHubService;
}
public async Task<ActionResult> StartCall()
{
var response = await _gitHubService.Client.GetAsync("/repos/aspnet/docs/issues");
}
}