Как правильно создать и использовать HttpClient в .NET?

«Как правильно создать и использовать HttpClient в .NET?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Правильное создание HttpClient критически важно для производительности и надежности приложения. Прямое создание экземпляра через new HttpClient() в долгоживущих сервисах ведет к исчерпанию сокетов. Рекомендуемый подход — использование IHttpClientFactory.

1. Предпочтительный способ: IHttpClientFactory (ASP.NET Core)

Регистрация в DI-контейнере (Program.cs):

builder.Services.AddHttpClient(); // Базовая регистрация
// Или с именованным клиентом и настройками:
builder.Services.AddHttpClient("GitHubClient", client =>
{
    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("User-Agent", "MyApp");
});

Использование в сервисе:

public class MyApiService
{
    private readonly HttpClient _httpClient;
    // Инжектируем фабрику
    public MyApiService(IHttpClientFactory httpClientFactory)
    {
        // Создаем клиент. Его жизненный цикл управляется фабрикой.
        _httpClient = httpClientFactory.CreateClient();
        // Или используем именованного клиента:
        // _httpClient = httpClientFactory.CreateClient("GitHubClient");
    }

    public async Task<string> GetDataAsync()
    {
        try
        {
            var response = await _httpClient.GetStringAsync("/users/octocat/repos");
            return response;
        }
        catch (HttpRequestException e)
        {
            // Логирование ошибки
            Console.WriteLine($"Request error: {e.Message}");
            throw;
        }
    }
}

2. Использование для разовых запросов Если клиент не инжектируется (например, в консольном приложении), используйте фабрику для создания и последующей правильной утилизации:

var services = new ServiceCollection();
services.AddHttpClient();
var serviceProvider = services.BuildServiceProvider();

var factory = serviceProvider.GetRequiredService<IHttpClientFactory>();
var client = factory.CreateClient();
// ... использовать client
// Не нужно вызывать Dispose() вручную — фабрика управляет этим.

Преимущества IHttpClientFactory:

  • Управление пулом соединений: Избегает проблемы исчерпания сокетов ("Socket exhaustion").
  • Централизованная конфигурация: Настройки базового адреса, таймаутов, заголовков задаются в одном месте.
  • Интеграция с Polly: Легко добавить политики повтора, размыкателя цепи.
  • Внедрение зависимостей: Клиенты легко тестируются и конфигурируются.