TLDR;
ViewComponent
s не поддерживают типизированных клиентов из коробки. Чтобы решить эту проблему, добавьте вызов к AddViewComponentsAsServices()
в конце вызова к services.AddMvc(...)
.
После довольно долгого чата , который не позволял воспроизвести вашу проблему, мы сначала определили, что наблюдаемая проблема относится только к ViewComponent
s. Даже при вызове IServiceCollection.AddHttpClient<SomeViewComponent>()
передача экземпляра HttpClient
в конструктор SomeViewComponent
просто отказалась работать.
Однако сидение нового класса (SomeService
) между SomeComponent
и HttpClient
работает, как ожидалось. Это то, что документы называют типизированным клиентом . Код выглядит примерно так:
// 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)
{
// ...
}
}
Как я уже говорил, этот подход работает - система ASP.NET Core DI очень рада создать экземпляр SomeService
и его типизированный экземпляр HttpClient
.
Чтобы переформулировать исходную проблему, возьмите следующий пример кода:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<SomeViewComponent>();
// ...
}
public class SomeViewComponent
{
public SomeViewComponent(HttpClient httpClient)
{
// ...
}
}
В этом случае система ASP.NET Core DI отказывается создавать экземпляр SomeViewComponent
из-за невозможности разрешить HttpClient
. Оказывается, это не специфично , просто - ViewComponent
с: оно также относится к Controller
с и TagHelper
с (спасибо Крису Пратту за подтверждение TagHelper
с).
Интересно, что также работает следующее:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<SomeViewComponent>();
// ...
}
public class SomeViewComponent
{
public SomeViewComponent(IHttpClientFactory httpClientFactory)
{
var httpClient = httpClientFactory.CreateClient("SomeViewComponent")
// ...
}
}
В этом примере мы используем тот факт, что для вызова AddHttpClient<SomeViewComponent>
зарегистрирован клиент с именем .
Чтобы иметь возможность вводить HttpClient
непосредственно в ViewComponent
, мы можем добавить вызов к AddViewComponentsAsServices
, когда мы регистрируем MVC с DI:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(...)
.AddViewComponentsAsServices();
// ...
}
AddControllersAsServices
и AddTagHelpersAsServices
также могут быть вызваны для добавления одинаковой поддержки для Controller
s и TagHelpers
соответственно.
Если мы посмотрим на документы более внимательно, становится ясно, что ни один из приведенных там примеров не вставляет HttpClient
в Controller
s и др. - об этом подходе просто нет никакого упоминания.
К сожалению, я недостаточно знаю о системе ASP.NET Core DI, чтобы точно объяснить , почему работает так, как работает: приведенная выше информация просто объясняет Что вместе с решением. Крис Пратт открыл выпуск в Github для обновления документов, чтобы расширить его.