Asp.net core 在.NET Core 2中注册基于作用域的HttpClient

Asp.net core 在.NET Core 2中注册基于作用域的HttpClient,asp.net-core,.net-core,asp.net-core-2.0,asp.net-core-webapi,coreclr,Asp.net Core,.net Core,Asp.net Core 2.0,Asp.net Core Webapi,Coreclr,我有NetCore2WebAPI应用程序。在这个过程中,我必须调用客户端A的API来获取一些数据。所以我使用HttpClient来调用它。客户端A还要求我在头中传递用户ID和密码 因此,与直接注入HttpClient不同,我使用了HttpClient包装器,如下所示 public class ClientA : IClientA { private readonly HttpClient _httpClient; public ClientA(HttpClient httpCl

我有NetCore2WebAPI应用程序。在这个过程中,我必须调用客户端A的API来获取一些数据。所以我使用HttpClient来调用它。客户端A还要求我在头中传递用户ID和密码

因此,与直接注入
HttpClient
不同,我使用了
HttpClient
包装器,如下所示

public class ClientA : IClientA
{
    private readonly HttpClient _httpClient;

    public ClientA(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<string> GetData()
    {
        return await _httpClient.HttpGetAsync("someurl");
    }
 }
然后我在Startup.cs中注册所有内容

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMyService, MyService>();           

        services.AddScoped(factory =>
        {
            Func<Task<IClientA>> provider = async () =>
            {
                using (var dbContext = factory.GetService<MyDBContext>())
                {
                    // get userid and password from database here

                    var httpClient = new HttpClient();
                    httpClient.DefaultRequestHeaders.Add("UserId",userid);
                    httpClient.DefaultRequestHeaders.Add("Password",password);
                    return new ClientA(httpClient);
                }
            };

            return provider;
        });
    }
解决了我的问题

   services.AddScoped<IClientA>(factory =>
    {            
            var dbContext = factory.GetService<MyDBContext>();                
                // get userid and password from database here

                var httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Add("UserId",userid);
                httpClient.DefaultRequestHeaders.Add("Password",password);
                return new ClientA(httpClient);
    });
services.AddScoped(工厂=>
{            
var dbContext=factory.GetService();
//在此处从数据库获取用户ID和密码
var httpClient=新的httpClient();
httpClient.DefaultRequestHeaders.Add(“UserId”,UserId);
httpClient.DefaultRequestHeaders.Add(“密码”,Password);
返回新客户(httpClient);
});

您不希望在限定范围的上下文中实例化httpclient,即为每个请求创建httpclient实例,这不是该类的推荐使用模式。(不会很好地扩展)

根据您的设置,为每个客户创建一个单独的接口(假设有少量客户)-可能在其实现中有代码访问安全需求(启用身份模拟?)

这将a)扩展良好b)每个客户每个应用程序实例/启动只运行一次,c)强制执行访问检查以了解使用情况


此外,此答案与您的标题要求相关-

该注册的某些内容看起来不对劲。您正在注册用于创建客户端的函数,而不是客户端本身。yeeeks@Nkosi你是对的。复制粘贴问题在我这边。没有必要注入HttpClient。这是一个实用类。您应该根据需要手动创建实例。如果有的话,请使用选项模式(例如,
IOptions
)注入HttpClient所需的参数。这不是相同的代码。最初的代码是重新调整函数的,而这段代码实际上返回了IClientAI。对于开发人员来说,这段代码比一大堆句子更具解释性:)我会记住这一点,因为这是一个范围注册,这段代码仍在为每个用户请求实例化http客户端,这意味着它在加载时会失败。(请参阅我答案中的链接)。这是一个严重的反模式,如果发生足够的负载,它将破坏应用程序的稳定性!如果您的应用程序处理的请求不多,它可能会起作用,但如果他们的应用程序处理的请求不止这些,则任何人都不应使用此解决方案。请不要创建所有类型的HttpClient,请使用IHttpClientFactory来创建。注册HttpClient的singleton实例可能可以,但如果您必须使用请求和响应Http头,然后,在每次请求/响应之后,您都必须不断清除Http头。否则,它们将在HttpClient进入后被缓存singlton@LP13您可以有一个单例,然后使用SendAsync方法处理一个请求,该请求专门处理所需的头(使头与单例分开/解耦)。例如:HttpRequestMessage请求=新建HttpRequestMessage(HttpMethod.Delete,url);request.Headers.Authorization=新的AuthenticationHeaderValue(“承载者”,UserSpecificAccessToken);HttpResponseMessage response=等待客户端.SendAsync(请求);(客户端是单例/静态HttpClient实例)
   public class ClientB(HttpClient client)
   {
        private readonly _httpClient;
        public class ClientB(HttpClient client)
        {
           _httpClient = client;
        }

        public string CallClientB(string url)
        {
            // here ClientB will receive ClientA's credentials
            return await _httpClient.HttpGetAsync(url);
        }
   }
   services.AddScoped<IClientA>(factory =>
    {            
            var dbContext = factory.GetService<MyDBContext>();                
                // get userid and password from database here

                var httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Add("UserId",userid);
                httpClient.DefaultRequestHeaders.Add("Password",password);
                return new ClientA(httpClient);
    });