ASP.NET 核心类型客户端中的 IHttpClientFactory
IHttpClientFactory in ASP.NET Core Typed Clients
当我尝试使用 HttpClient 的类型化客户端时收到错误消息,如下所述:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2
这是我的设置:
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
services.AddHttpClient<IPStackService>(c =>
{
c.BaseAddress = new Uri(Configuration["IPStackURL"]);
});
services.AddHttpContextAccessor();
services.AddTransient<IIPStackService, IPStackService>();
}
控制器:
[Route("api/[controller]")]
[ApiController]
public class RenderController : ControllerBase
{
private IConfiguration _configuration;
private readonly ILogger _logger;
private IIPStackService _ipMetaDataService;
public RenderController(IConfiguration configuration,
ILogger<RenderController> logger,
IIPStackService ipStackService)
{
_configuration = configuration;
_ipStackService = ipStackService;
_logger = logger;
}
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[Produces("text/plain")]
public async Task<ActionResult> GetAsync(string hostId, string clientUtc)
{
var ip = Common.ResolveIPAddress(HttpContext);
var ipMetaData = await _ipStackService.GetByIPAsync(ip, _configuration["AccessKey"]);
// removed for clarity
return allowed ? Ok(true) : Ok(null);
}
}
服务:
public class IPStackService : IIPStackService
{
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public IPStackService(ILogger<IPStackService> logger, HttpClient client)
{
_logger = logger;
_httpClient = client;
}
public async Task<IPMetaDataModel> GetByIPAsync(string ip, string accessKey)
{
var ipMetaData = new IPMetaDataModel();
var response = await _httpClient.GetAsync($"/{ip}?access_key={accessKey}");
response.EnsureSuccessStatusCode();
// removed for clarity
return ipMetaData;
}
}
收到错误:
An unhandled exception occurred while processing the request.
InvalidOperationException: Unable to resolve service for type
'System.Net.Http.HttpClient' while attempting to activate
'WebScreen.Gate.Services.IPStackService'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type
serviceType, Type implementationType, CallSiteChain callSiteChain,
ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
如何为 HttpClient 正确设置类型化客户端?
IPStackService
的 Activator(代码反射)无法在 DI 集合中找到 HttpClient
,这就是您遇到异常的原因(特别针对 services.AddTransient<IIPStackService, IPStackService>()
)。
顺便说一句,您在 DI 集合中添加了两次服务 IPStackService
:
services.AddHttpClient<IPStackService>(...);
.
services.AddTransient<IIPStackService, IPStackService>()
;
你只需要一个,因为你使用的是类型化客户端,你可以通过删除第二个并保留第一个来解决你的问题,并通过将合同添加到实现中来稍微改变第一个,如下所示:
services.AddHttpClient<IIPStackService, IPStackService>(c =>
{
c.BaseAddress = new Uri(Configuration["IPStackURL"]);
});
AddHttpClient
将负责将 HttpClient
绑定到您的服务。
如果您想使用 services.AddTransient<IIPStackService, IPStackService>();
而不是 services.AddHttpClient
,那么您需要将 HttpClient
添加到您的 DI 集合中:
services.AddTransient<HttpClient>();
当我尝试使用 HttpClient 的类型化客户端时收到错误消息,如下所述: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2
这是我的设置:
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
services.AddHttpClient<IPStackService>(c =>
{
c.BaseAddress = new Uri(Configuration["IPStackURL"]);
});
services.AddHttpContextAccessor();
services.AddTransient<IIPStackService, IPStackService>();
}
控制器:
[Route("api/[controller]")]
[ApiController]
public class RenderController : ControllerBase
{
private IConfiguration _configuration;
private readonly ILogger _logger;
private IIPStackService _ipMetaDataService;
public RenderController(IConfiguration configuration,
ILogger<RenderController> logger,
IIPStackService ipStackService)
{
_configuration = configuration;
_ipStackService = ipStackService;
_logger = logger;
}
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[Produces("text/plain")]
public async Task<ActionResult> GetAsync(string hostId, string clientUtc)
{
var ip = Common.ResolveIPAddress(HttpContext);
var ipMetaData = await _ipStackService.GetByIPAsync(ip, _configuration["AccessKey"]);
// removed for clarity
return allowed ? Ok(true) : Ok(null);
}
}
服务:
public class IPStackService : IIPStackService
{
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public IPStackService(ILogger<IPStackService> logger, HttpClient client)
{
_logger = logger;
_httpClient = client;
}
public async Task<IPMetaDataModel> GetByIPAsync(string ip, string accessKey)
{
var ipMetaData = new IPMetaDataModel();
var response = await _httpClient.GetAsync($"/{ip}?access_key={accessKey}");
response.EnsureSuccessStatusCode();
// removed for clarity
return ipMetaData;
}
}
收到错误:
An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'System.Net.Http.HttpClient' while attempting to activate 'WebScreen.Gate.Services.IPStackService'. Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
如何为 HttpClient 正确设置类型化客户端?
IPStackService
的 Activator(代码反射)无法在 DI 集合中找到 HttpClient
,这就是您遇到异常的原因(特别针对 services.AddTransient<IIPStackService, IPStackService>()
)。
顺便说一句,您在 DI 集合中添加了两次服务 IPStackService
:
services.AddHttpClient<IPStackService>(...);
.services.AddTransient<IIPStackService, IPStackService>()
;
你只需要一个,因为你使用的是类型化客户端,你可以通过删除第二个并保留第一个来解决你的问题,并通过将合同添加到实现中来稍微改变第一个,如下所示:
services.AddHttpClient<IIPStackService, IPStackService>(c =>
{
c.BaseAddress = new Uri(Configuration["IPStackURL"]);
});
AddHttpClient
将负责将 HttpClient
绑定到您的服务。
如果您想使用 services.AddTransient<IIPStackService, IPStackService>();
而不是 services.AddHttpClient
,那么您需要将 HttpClient
添加到您的 DI 集合中:
services.AddTransient<HttpClient>();