4

I am planning to use Microsoft.Extensions.Http package in my ASP.NET Framework 4.7.2 Webforms project. Since there is no built-in DI Container in .NET Framework, I am not using the DI packages. Based on this answer, I am not sure about the last line -

Microsoft.Extensions.Http provides the HttpClientFactory only, not the new optimized HttpClient. This is only available in .NET Core 2.1

Can I implement IHttpClientFactory without DI and using singleton method in my Framework project and get rid of the 2 problems of using HttpClient directly - Socket Exhaustion and DNS resolution? Is there something else that needs to be done based on the above comment

Jatin
  • 83
  • 7

1 Answers1

8

Unfortunately, the use of the HttpClientFactory is tightly integrated with the DI framework. Fortunately, creating a new IHttpClientFactory without making use of the full DI infrastructure can be done in a few lines:

IHttpClientFactory factory = new ServiceCollection()
    .AddHttpClient()
    .BuildServiceProvider()
    .GetRequiredService<IHttpClientFactory>();

With the code above you create new new service provider (which is the MS.DI Container) that just contains the registrations for the HTTP client package, which includes a registration for IHttpClientFactory, and the IHttpClientFactory is directly pulled from the container. The factory is stored in a variable, while the container itself is no longer used.

A full working Console application would like like this:

// This requires the 'Microsoft.Extensions.Http` package to be installed
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using System.Threading.Tasks;

internal class Program
{
    static async Task Main(string[] args)
    {
        IHttpClientFactory factory = new ServiceCollection()
            .AddHttpClient()
            .BuildServiceProvider()
            .GetRequiredService<IHttpClientFactory>();

        HttpClient client = factory.CreateClient();

        string html = await client.GetStringAsync(
            "https://blogs.cuttingedge.it/steven/p/commands");

        Console.WriteLine(html);

        Console.ReadLine();
    }
}

Best is to cache the IHttpClientFactory for the lifetime of your application and not recreate it on the fly.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • Hi @Steven, I have implemented the IHttpClientFactory very similar to what you've written, actually inspired from [this](https://stackoverflow.com/a/63392908/15423813) I just wanted to make sure that this implementation is full-proof and won't cause issues. Because this comment that Panagiotis has given [here](https://stackoverflow.com/a/51480287/15423813) I was confused. "Microsoft.Extensions.Http provides the HttpClientFactory only, not the new optimized HttpClient. This is only available in .NET Core 2.1" So we should be good with the approach you provided, right? – Jatin Jan 10 '23 at 06:43
  • Hi @Steven, Don't we have to dispose the IServiceProvider? Or create scope on it? And can I use the same approach to create ILogger in a WebForms 4.7 app? – Jatin Jan 20 '23 at 17:00
  • 1
    I would say that for this particular use case, there is no need to create a scope (as `IHttpClientFactory` is registered as singleton) and there's no need to disposed of the `IServiceProvider` when the application closes (as the only thing it manages is the `IHttpClientyFactory`). Trying to dispose of the service provider or manage a scope only complicates the solution, while providing no extra benefits. – Steven Jan 23 '23 at 20:21
  • Just 2 more questions - 1) If we want to use ILogger in a .NET Framework Web App, could we do what I've written here, i.e. the question I have asked [here](https://stackoverflow.com/questions/75091781/get-an-ilogger-instance-for-app-insights-from-servicecollection-in-a-webforms-n). Btw, if you could help me with that question, would be really helpful :) 2) We also want to register a few custom classes. In such a case, how would we pass the IServiceProvider (to create scopes) to the different consumer classes by using the MS DI in Framework? We want Constructor Injection only. @Steven – Jatin Jan 26 '23 at 14:46