Reputation: 1174
I would like to wrap some timing logic around all calls made through HttpClient from my ASP.NET Core app, including calls made from 3rd party libraries.
Does HttpClient
in .NET Core have something I can plug into to run some code on every request?
Upvotes: 17
Views: 15607
Reputation: 25019
Yes, it does. HttpClient
produces a HTTP request via DelegatingHandler
chain. To intercept the HttpClient
request, you can add a derived handler with overrided SendAsync
method to that chain.
Usage:
var handler = new ExampleHttpHandler(fooService);
var client = new HttpClient(handler);
var response = await client.GetAsync("http://google.com");
Implementation:
public class ExampleHttpHandler : DelegatingHandler
{
//use this constructor if a handler is registered in DI to inject dependencies
public ExampleHttpHandler(FooService service) : this(service, null)
{
}
//Use this constructor if a handler is created manually.
//Otherwise, use DelegatingHandler.InnerHandler public property to set the next handler.
public ExampleHttpHandler(FooService service, HttpMessageHandler innerHandler)
{
//the last (inner) handler in the pipeline should be the "real" one.
//To make a HTTP request, create a HttpClientHandler instance.
InnerHandler = innerHandler ?? new HttpClientHandler();
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
//add any logic here
return await base.SendAsync(request, cancellationToken);
}
}
BTW, I recommend moving as much business logic out of a custom handler as possible to simplify unit-testing it. Also, check HttpClient
lifetime guidelines for best practices in .NET http client creation.
Upvotes: 14