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?
An interceptor is a class that implements IInterceptor interface (of Castle Windsor). It defines the Intercept method which gets an IInvocation argument. With this invocation argument, we can investigate the executing method, method arguments, return value, method's declared class, assembly and much more.
What are Interceptors? Interceptors check each and every incoming and outgoing request to the server and are also able to manipulate them before actually sending to the server.
Using HttpClient to Send HTTP PATCH Requests in ASP.NET Core. In this article, we learn how to use HttpClient to send HTTP PATCH requests to achieve partial updates of our resources, thus improving the application's performance. Using Streams with HttpClient to Improve Performance and Memory Usage.
The HttpClient instances injected by DI, can be disposed of safely, because the associated HttpMessageHandler is managed by the factory. As a matter of fact, injected HttpClient instances are Scoped from a DI perspective.
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(new ExampleHttpHandler(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 a "real" handler.
//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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With