These days in the .NET world, it's common to work with external services that require authentication or specific header configurations to function properly. Trust me—you don’t want to repeat the same setup logic everywhere you use HttpClient
.
That’s where the DelegatingHandler
class from the .NET library becomes incredibly useful.
A DelegatingHandler
lets you intercept and modify HTTP requests before they are sent to the external service. This gives you the flexibility to apply required configurations like setting headers.
Just follow these 3 simple steps:
- Create a custom handler
// Create a handler derived from DelegatingHandler
public class AuthHandler : DelegatingHandler
{
// Override SendAsync
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Configure required header before actual request
string token = await GetAccessTokenAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Headers.Add("Type", "INTERNAL");
return await base.SendAsync(request, cancellationToken);
}
}
- Register it in the dependency injection (DI) container
builder.Services.AddTransient<AuthHandler>();
builder.Services.AddHttpClient("VendorApi", client =>
{
client.BaseAddress = new Uri("https://vendor.com");
})
.AddHttpMessageHandler<AuthHandler>();
- Inject and use HttpClient throughout your code—without worrying about repeating header logic
app.MapGet("posts", async (IHttpClientFactory httpClientFactory) =>
{
HttpClient httpClient = httpClientFactory.CreateClient("VendorApi");
HttpResponseMessage response = await httpClient.GetAsync("posts");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
})
.WithName("posts")
.WithOpenApi();
Learn more about DelegatingHandler
and IHttpClientFactory
here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-9.0