.Net Core 1.1 HttpClient with DI

前端 未结 1 1131
夕颜
夕颜 2021-01-26 20:05

Following is the code I am using:

  namespace MySite.Api
{
    using System.Collections.Specialized;
    using System.Linq;
    using System.Net;
    using Syste         


        
相关标签:
1条回答
  • 2021-01-26 20:54

    HttpClient should be singleton-scoped. There's a finite number of connections available on your machine, and since HttpClient holds on to connections it creates, having multiple instances floating around can quickly exhaust your connection pool.

    Beginning with ASP.NET Core 2.1, there exists IHttpClientFactory which provides a simple and reusable way of injecting properly scoped HttpClient instances. However, since you're using 1.1, that's not available to you. The recommended path would be to upgrade your project to 2.1. The 1.X line of ASP.NET Core is frankly trash. It wasn't ready for production use, despite being an official release.

    If you insist on sticking with 1.1, then you'll need to implement your own method of reusing HttpClient instances. The most straightforward way is to use "accessor" classes, which you can then utilize to inject different HttpClients into different objects. For example:

    public class ApiHttpClientAccessor : IDisposable
    {
        public ApiHttpClientAccessor()
        {
            HttpClient = new HttpClient
            {
                BaseAddress = new Uri("https://foo.com")
            };
        }
    
        public HttpClient HttpClient { get; }
    
        private bool _disposed;
    
        public virtual void Dispose(bool disposing)
        {
            if (disposing && !_disposed)
            {
                HttpClient.Dispose();
            }
            _disposed = true;
         }
    
         public bool Dispose() =>
             Dispose(true);        
    }
    

    Then, you can register this accessor class as a singleton, meaning it will only be created once (so the contained HttpClient will also only be created once). Then, set up your class to accept this accessor in its constructor:

    public class ApiQuery : IApiQuery
    {
        private readonly HttpClient _client;
    
        public ApiQuery(ApiHttpClientAccessor httpClientAccessor)
        {
            _client = (httpClientAccessor ?? throw new ArgumentNullException(nameof(httpClientAccessor))).HttpClient;
        }
    
        ...
    }
    

    And in Startup.cs:

    services.AddSingleton<ApiHttpClientAccessor>();
    services.AddTransient<IApiQuery, ApiQuery>();
    
    0 讨论(0)
提交回复
热议问题