簡體   English   中英

無法解析“System.Net.Http.HttpClient”類型的服務

[英]Unable to resolve service for type 'System.Net.Http.HttpClient'

我創建了一個ViewComponent類,它使用HttpClient調用REST API ,這是代碼:

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:嘗試激活 MyApp.ViewComponents.ProductsViewComponent 時無法解析類型“System.Net.Http.HttpClient”的服務

我以這種方式在Startup中可用的ConfigureService方法中注入了HttpClient

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

更新:

我也注冊了ProductsViewComponent ,同樣的錯誤。

我有一個類似的問題 - 問題是雙重注冊:

services.AddHttpClient<Service>();
services.AddSingleton<Service>();  // fixed by removing this line

TLDR; ViewComponent不支持開箱即用的類型化客戶端 要解決此問題,請在對services.AddMvc(...)的調用末尾添加對AddViewComponentsAsServices()的調用。


經過一段很長的聊天,因為能夠重現您的問題,我們最初確定所觀察到的問題是特定於ViewComponent的。 即使調用IServiceCollection.AddHttpClient<SomeViewComponent>() ,將HttpClient的實例傳遞給SomeViewComponent的構造函數也只是拒絕工作。

但是,SomeComponentHttpClient之間SomeComponent一個新類 ( SomeService ) 可以按預期工作。 這就是文檔所說的類型化客戶端 代碼看起來有點像這樣:

// 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)
    {
        // ...
    }
}

在這種情況下,由於無法解析HttpClient ,ASP.NET Core DI 系統拒絕創建SomeViewComponent的實例。 事實證明,這不僅僅適用ViewComponent s:它也適用於Controller s 和TagHelper s(感謝 Chris Pratt 確認TagHelper s)。

有趣的是,以下也有效:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient<SomeViewComponent>();
    // ...
}

public class SomeViewComponent
{
    public SomeViewComponent(IHttpClientFactory httpClientFactory)
    {
        var httpClient = httpClientFactory.CreateClient("SomeViewComponent")
        // ...
    }
}

在此示例中,我們利用了對AddHttpClient<SomeViewComponent>的調用為我們注冊了一個命名客戶端的事實。

為了能夠將HttpClient直接注入到ViewComponent ,我們可以在向 DI 注冊 MVC 時添加對AddViewComponentsAsServices的調用:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(...)
        .AddViewComponentsAsServices();
    // ...
}

AddControllersAsServicesAddTagHelpersAsServices也可稱為添加了同樣的支持Controller S和TagHelpers分別。

如果我們更仔細地查看文檔,很明顯那里的示例都沒有將HttpClient注入Controller等 - 根本沒有提到這種方法。

不幸的是,我不知道有足夠的了解ASP.NET的核心DI系統,以便能夠准確解釋為什么這個工作方式是這樣:我上面提供的信息只是解釋了什么一起的解決方案。 Chris Pratt 已在 Github 中打開了一個問題,以便更新文檔以對此進行擴展。

我在Azure Function版本 2 中遇到了類似的錯誤。根據本文檔,我們應該能夠將IHttpClientFactory添加為依賴項。 在我的 Azure 函數中添加這個DI后,我收到了下面提到的錯誤。

Microsoft.Extensions.DependencyInjection.Abstractions:嘗試激活“OServiceBus.Adapter.FetchDataFromSubscription1”時無法解析“System.Net.Http.IHttpClientFactory”類型的服務

問題是我沒有覆蓋 Configure 函數來添加HttpClient作為注冊的依賴項。 所以我只是在我的 Azure Function 的根目錄中創建了一個名為Statup的類,如下所示。

使用 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();
        }
    }
}

添加后,我的功能開始正常工作。 希望能幫助到你。

您似乎混淆了兩個視圖組件。 您將FixturesViewComponent注冊為“命名的 HTTP 客戶端”,但您嘗試在ProductsViewComponent注入一個HttpClient實例。

將 HttpClient 注冊更改為ProductsViewComponent應該會有所幫助:

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

我有一條類似的錯誤消息,試圖將外部 REST 服務的包裝器作為接口注入到我的控制器中。 我需要在 ConfigureServices 中更改以下內容:

services.AddHttpClient<IMyServiceWrapper>("MyServiceWrapper", client =>
{
   client.BaseAddress = new Uri("http://some_service/api");
}

services.AddHttpClient<IMyServiceWrapper, MyServiceWrapper>("MyServiceWrapper", client =>
{
   client.BaseAddress = new Uri("http://some_service/api");
}

為了能夠在我的控制器的構造函數中使用接口:

public MyController(IMyServiceWrapper myService)
{
  _myService = myService;
}

用於使用模擬服務測試 myController。

也許它會有所幫助,但在我的情況下這是有效的:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService,MyService>(); // my usual DI injection of a service that can be mocked
    services.AddHttpClient<IMyService,MyService>(client => {
        client.BaseAddress = new Uri("https://myservice.com/api");
    }); // notice that I use IMyService for the reference of the registration AND implementation to where it will be injected.
}

public class MyService
{
    public MyService(HttpClient client)
    {
        // client.BaseAddress is properly set here
    }
}

public class MyController : Controller
{
    public MyController(IMyService service) // used by the interface
    {}
}

我也試過services.AddHttpClient<IMyService>() ,由於缺少它的構造函數而無法解決。 還嘗試了services.AddHttpClient<MyService>()如上所述,但它不會解析配置的實例,如上所述。

所以重要的部分是需要使用用於引用解析類型的類。 所以這也有效:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<MyService>(); // registering the type itself, not via interface
    services.AddHttpClient<MyService>(client => {
        client.BaseAddress = new Uri("https://myservice.com/api");
    }); // it's ok here, since it will be resolved by it's own type name
}

public class MyService
{
    public MyService(HttpClient client)
    {
        // client.BaseAddress is properly set here
    }
}

public class MyController : Controller
{
    public MyController(MyService service) // used by the type directly
    {}
}

這有點道理,但文檔和示例可能會更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM