Delegating Handlers in C#
Delegating handlers are cousins of asp.net core middleware. Lets talk a bit about middlewares, this will help us understand delegating handler easy.
This post is a contribution to the .NET advent calendar 2021. https://dotnet.christmas/
Middlewares in asp.net core are super useful and super convenient to write. If you have used asp.net core for a while now, you may come across them. If not, the docs page give a very good introduction. Here it is. The docs are so good, they are a good introduction and more. The docs keep getting better over time. Middleware is a piece of code that can be fitted in a request pipeline.
A middleware resides in the asp.net core application that accepts http requests. The Http request flows into the first middleware and if it wants passes on the request to the next. Until, there is a middleware the creates a response and the response flows back from the middleware that generated the response up until the first middleware. Finally the response is sent back to the client that actually made the http request over the network.
Delegating handlers are similar to middlewares but on the client side. So, if you are making a http request using the httpClient you can leverage delegating handlers.
Here is an example of a typed http client and then below you can see this being registred in the builder.Services.
So, how do you create a delegating handler ?
Quite simple, there is a type called DelegatingHandler in the namespace System.Net.Http. Just inherit that type. And override the following method:
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Here is an example of a Delegating handler made simply for logging purposes. The method SendAsync() is overriden. It logs before the request and after the request is made and a response received.
public class LoggingHandler : DelegatingHandler
private readonly ILogger<LoggingHandler> _logger;
public LoggingHandler(ILogger<LoggingHandler> logger)
_logger = logger;
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
_logger.LogInformation("Right before making http request");
var response = await base.SendAsync(request, cancellationToken);
_logger.LogInformation("Response has been received");
Here is how you add it to your httpClient. Just call AddHttpMessageHandler.
This is just an example of how you can intercept the requests made by the http client. The important point about delegating handlers is that you can reuse them. That means you can make use of the same handlers with multiple httpclient.
What can you use these handlers for?
Well, asp.net core framework provides a lot in terms of functionality and may not have to do any thing custom. But, if you want it its there.
If you want to implement a retry mechanism, my go to library for that is Polly. But if you want make something custom for your needs. These handlers may come in handy to implement your own retry logic.
Custom Headers can be added for all your requests and this concern can be separated out in a Delegating handler.
If you want reuse of functionality in your httpClient requests, Delegating Handlers are definitely a good option.
Thank you for your time. Until next time. Cheers.