Solución:
Tuve un problema similar: el problema estaba en el registro doble:
services.AddHttpClient<Service>();
services.AddSingleton<Service>(); // fixed by removing this line
TLDR;
ViewComponent
s no admiten clientes mecanografiados de fábrica. Para resolver esto, agregue una llamada a AddViewComponentsAsServices()
al final de la llamada a services.AddMvc(...)
.
Después de una charla bastante larga que se basó en la posibilidad de reproducir su problema, determinamos inicialmente que el problema que se observa es específico de ViewComponent
s. Incluso con una llamada a IServiceCollection.AddHttpClient<SomeViewComponent>()
, pasando una instancia de HttpClient
en SomeViewComponent
s constructor simplemente se negó a trabajar.
Sin embargo, sentarse en una nueva clase (SomeService
) Entre SomeComponent
y HttpClient
funciona como se esperaba. Esto es lo que los documentos denominan cliente escrito. El código se parece un poco a esto:
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<SomeService>();
// ...
}
// SomeService.cs
public class SomeService
{
public SomeService(HttpClient httpClient)
{
// ...
}
}
// SomeViewComponent.cs
public class SomeViewComponent
{
public SomeViewComponent(SomeService someService)
{
// ...
}
}
Como ya he dicho, este enfoque funciona: el sistema ASP.NET Core DI está muy feliz de crear la instancia de SomeService
y está escrito HttpClient
ejemplo.
Para reformular el problema original, tome el siguiente código de ejemplo:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<SomeViewComponent>();
// ...
}
public class SomeViewComponent
{
public SomeViewComponent(HttpClient httpClient)
{
// ...
}
}
En este caso, el sistema ASP.NET Core DI se niega a crear una instancia de SomeViewComponent
por no poder resolver HttpClient
. Resulta que esto no es específico sólo para ViewComponent
s: también se aplica a Controller
arena TagHelper
s (gracias a Chris Pratt por confirmar para TagHelper
s).
Curiosamente, lo siguiente también funciona:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<SomeViewComponent>();
// ...
}
public class SomeViewComponent
{
public SomeViewComponent(IHttpClientFactory httpClientFactory)
{
var httpClient = httpClientFactory.CreateClient("SomeViewComponent")
// ...
}
}
En este ejemplo, aprovechamos el hecho de que la llamada a AddHttpClient<SomeViewComponent>
registró un cliente designado para nosotros.
Para poder inyectar HttpClient
directamente en un ViewComponent
, podemos agregar una llamada a AddViewComponentsAsServices
cuando registramos MVC con DI:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(...)
.AddViewComponentsAsServices();
// ...
}
AddControllersAsServices
y AddTagHelpersAsServices
También se puede llamar para agregar el mismo soporte para Controller
arena TagHelpers
respectivamente.
Si miramos los documentos más de cerca, está claro que ninguno de los ejemplos inyecta un HttpClient
en Controller
s et al: simplemente no se menciona este enfoque en absoluto.
Desafortunadamente, no sé lo suficiente sobre el sistema ASP.NET Core DI para poder explicar exactamente por qué esto funciona de la manera que lo hace: la información que he proporcionado anteriormente simplemente explica el qué junto con una solución. Chris Pratt ha abierto un problema en Github para que los documentos se actualicen para ampliar esto.
Parece que tienes dos componentes de vista mezclados. Estás registrando el FixturesViewComponent
como un “cliente HTTP con nombre”, pero intentas inyectar un HttpClient
instancia en el ProductsViewComponent
.
Cambiar el registro de HttpClient a ProductsViewComponent
debería ayudar:
services.AddHttpClient<ProductsViewComponent>(options =>
{
options.BaseAddress = new Uri("http://80.350.485.118/api/v2");
});