â
What is HttpClient
?
HttpClient
is a built-in class in .NET used to send HTTP requests and receive HTTP responses from web APIs.
â Why is it used?
You use HttpClient
to:
-
ð Call external APIs or services
-
ðĨ Get data from a URL (like JSON)
-
ðĪ Send data (like POST, PUT requests)
-
ð Communicate over the internet (HTTP/HTTPS)
â Simple Example:
var client = new HttpClient();
var response = await client.GetStringAsync("https://api.example.com/data");
Console.WriteLine(response);
â
Why Not Use new HttpClient()
Directly?
Using new HttpClient()
in every request can cause:
-
Socket exhaustion (sockets are not released quickly).
-
Hard-to-test code.
-
No built-in support for resilience libraries like Polly.
ð§ 1. IHttpClientFactory
(Basic Usage)
â Best for:
-
Creating
HttpClient
instances on demand. -
Having control over how the client is configured at runtime.
ðĄ Example:
Startup.cs / Program.cs
builder.Services.AddHttpClient();
Usage in a service:
public class MyService
{
private readonly IHttpClientFactory _httpClientFactory;
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<string> GetDataAsync()
{
var client = _httpClientFactory.CreateClient();
return await client.GetStringAsync("https://api.example.com/data");
}
}
ð·ïļ 2. Named HttpClient
â Best for:
-
Calling multiple APIs with different configurations.
-
Centralizing configs (like base address, headers).
ðĄ Example:
Startup.cs / Program.cs
builder.Services.AddHttpClient("GitHubClient", client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.UserAgent.ParseAdd("HttpClientFactory-Sample");
});
Usage:
var client = _httpClientFactory.CreateClient("GitHubClient");
var response = await client.GetStringAsync("/users/octocat");
ðĻâðŧ 3. Typed HttpClient
â Best for:
-
Clean Dependency Injection (DI).
-
Testable services.
-
Automatically injects preconfigured
HttpClient
.
ðĄ Example:
Typed client class:
public class GitHubService
{
private readonly HttpClient _client;
public GitHubService(HttpClient client)
{
_client = client;
_client.BaseAddress = new Uri("https://api.github.com/");
_client.DefaultRequestHeaders.UserAgent.ParseAdd("HttpClientFactory-Sample");
}
public async Task<string> GetUserAsync(string username)
{
return await _client.GetStringAsync($"/users/{username}");
}
}
Register it:
builder.Services.AddHttpClient<GitHubService>();
Usage:
var result = await _gitHubService.GetUserAsync("octocat");
ð§ 4. Refit (Type-safe REST Client)
â Best for:
-
Declarative API definitions.
-
Auto-generates HTTP logic from interfaces.
-
Great with Polly, testability, and clean architecture.
ðĄ Install:
dotnet add package Refit.HttpClientFactory
Define interface:
public interface IGitHubApi
{
[Get("/users/{username}")]
Task<User> GetUserAsync(string username);
}
Register with Refit:
builder.Services.AddRefitClient<IGitHubApi>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.github.com/"));
Usage:
var user = await _gitHubApi.GetUserAsync("octocat");
â Summary Table
Method | Best For | Factory Access Needed | Testable |
---|---|---|---|
IHttpClientFactory | Flexible, low-level usage | â Yes | ð |
Named HttpClient | Multiple APIs with different settings | â Yes | ð |
Typed HttpClient | DI-friendly, clean architecture | â No | ðð |
Refit | Interface-based, declarative HTTP calls | â No (hidden under hood) | ððð |