我有NetCore2WebAPI应用程序。在此过程中,我必须调用客户端A的API来获取一些数据。所以我使用HttpClient来调用它。客户端A还要求我在标头中传递用户in和密码。
因此,我没有直接注入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");
}
}然后在服务中使用ClientA
public class MyService :IMyService
{
private readonly IClientA _clientA
public MyService(IClientA clientA)
{
_clientA= clientA
}
public void DoSomethig()
{
_clientA.GetData();
}
}然后我将在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;
});
}不管怎么说我都错了
System.InvalidOperationException:当试图激活'XXXXXXXXX.ClientA‘时,无法解析“System.Net.Http.HttpClient”类型的服务。在Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType,Type implementationType,ISet
1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet1 callSiteChain)
为简洁起见删除剩余异常
注意,在注册期间,我是HttpClient的newing-up实例,并将它传递给ClientA类,因为我必须设置userid和密码。
为了消除上述错误,我可以向HttpClient注册UserID,并在DI框架中注册密码,我猜这是可行的。
但是,在这种情况下,如果有另一个接受ClientB的客户端HttpClient,那么DI框架将注入具有用户in和密码的同一个httpclient。这将造成安全问题,因为ClientB将在请求头中看到ClientA的凭据。
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);
}
}发布于 2018-03-05 23:42:58
解决了我的问题
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);
});发布于 2018-03-06 00:07:16
您不希望在一个限定作用域的上下文中实例化httpclient,即创建每个请求的httpclient实例,这不是该类的推荐使用模式。(不能很好地扩展)。https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
为每个客户创建一个单独的接口(假设有少量的客户)--可能在其实现中有一个代码访问安全需求,这取决于您的设置(启用了身份模拟?)
这将是( a)扩展,b)每个应用程序实例/启动时每个客户只运行一次,以及( c)强制对使用情况进行访问检查。
而且,这个答案是连接的,并与您的头需求相关- HttpClient single instance with different authentication headers
https://stackoverflow.com/questions/49120741
复制相似问题