Не удалось разрешить службу для типа 'System.Net.Http.HttpClient' - PullRequest
0 голосов
/ 05 сентября 2018

Я создал ViewComponent класс, который вызывает REST API, используя HttpClient, это код:

public class ProductsViewComponent : ViewComponent
{
    private readonly HttpClient _client;

    public ProductsViewComponent(HttpClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    public async Task<IViewComponentResult> InvokeAsync(string date)
    {
        using(var response = await _client.GetAsync($"/product/get_products/{date}"))
        {
            response.EnsureSuccessStatusCode();
            var products = await response.Content.ReadAsAsync<List<Products>>();
            return View(products);
        }
    }
}

Я получаю эту ошибку:

InvalidOperationException: невозможно разрешить службу для типа «System.Net.Http.HttpClient» при попытке активировать MyApp.ViewComponents.ProductsViewComponent '

Я ввел HttpClient в методе ConfigureService, доступном в Startup, следующим образом:

 services.AddHttpClient<FixturesViewComponent>(options =>
 {
    options.BaseAddress = new Uri("http://80.350.485.118/api/v2");
 });

UPDATE:

Я тоже зарегистрировал ProductsViewComponent, та же ошибка.

Ответы [ 4 ]

0 голосов
/ 08 июля 2019

Я получил похожую ошибку в моей Azure Function версии 2. Согласно этому документу , мы должны иметь возможность добавить IHttpClientFactory в качестве зависимости. После добавления этого DI в мою функцию Azure я получил ошибку, указанную ниже.

Microsoft.Extensions.DependencyInjection.Abstractions: Невозможно разрешить службу для типа «System.Net.Http.IHttpClientFactory», пока пытаясь активировать 'OServiceBus.Adapter.FetchDataFromSubscription1'

Проблема заключалась в том, что я не переопределил функцию Configure, чтобы добавить HttpClient в качестве зарегистрированной зависимости. Поэтому я просто создал класс с именем Statup в корневом каталоге моей функции Azure следующим образом.

с использованием Microsoft.Azure.Functions.Extensions.DependencyInjection; используя Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(ServiceBus.Adapter.Startup))]
namespace ServiceBus.Adapter {
    public class Startup: FunctionsStartup {
        public override void Configure(IFunctionsHostBuilder builder) {
            builder.Services.AddHttpClient();
        }
    }
}

После добавления моя функция начала работать правильно. Надеюсь, это поможет.

0 голосов
/ 05 сентября 2018

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 для обновления документов, чтобы расширить его.

0 голосов
/ 14 февраля 2019

У меня была похожая проблема - проблема была в двойной регистрации:

services.AddHttpClient<Service>();
services.AddSingleton<Service>();  // fixed by removing this line
0 голосов
/ 05 сентября 2018

Кажется, что вы перепутали два компонента вида. Вы регистрируете FixturesViewComponent как «именованный HTTP-клиент», но пытаетесь внедрить экземпляр HttpClient в ProductsViewComponent.

Изменение регистрации HttpClient на ProductsViewComponent должно помочь:

services.AddHttpClient<ProductsViewComponent>(options =>
{
   options.BaseAddress = new Uri("http://80.350.485.118/api/v2");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...