🙋♀️ In my case I had to some work on a legacy .NET 2.2 Core ASP app (i.e. couldn't use the fancy attribute mentioned in mmoon's answer.
To complete Ahmed Alejo's answer, and in particular if you're taking the ASP.NET Core DI container road, I've noticed that if I left the two ctors as they were in the original answer, the whole thing was kabooming (i.e. getting the infamous exception: The 'DelegatingHandler' list is invalid because the property 'InnerHandler' of 'handler' is not null
).
So what I ended up doing was to not write any ctors, just as below 👇
public class UriQueryUnescapingHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var uri = request.RequestUri;
var unescapedQuery = Uri.UnescapeDataString(uri.Query);
var userInfo = string.IsNullOrWhiteSpace(uri.UserInfo) ? string.Empty : $"{uri.UserInfo}@";
var scheme = string.IsNullOrWhiteSpace(uri.Scheme) ? string.Empty : $"{uri.Scheme}://";
request.RequestUri = new Uri($"{scheme}{userInfo}{uri.Authority}{uri.AbsolutePath}{unescapedQuery}{uri.Fragment}");
return base.SendAsync(request, cancellationToken);
}
}
and then it just works like a charm when you're configuring the services that way 👇:
services.AddTransient<UriQueryUnescapingHandler>();
// whatever other services you need to set up beforehand
services
.AddRefitClient<IMyRefitService>(myRefitSettings)
.ConfigureHttpClient(c =>
{
// whatever relevant HttpClient-related configuration action goes here
})
.AddHttpMessageHandler<UriQueryUnescapingHandler>();