Ensuring HttpClient can be used safely as a singleton There has been talk recently of how we should be handling the lifetime of the System.Net.Http.HttpClient.

This article http://byterot.blogspot.co.uk/2016/07/singleton-httpclient-dns.html says that we should use it as a singleton, but we need to be careful about ensuring the connections are properly closed otherwise DNS changes won't be honoured.

I came up with the following message handler which can be injected in to an HttpClient to take care of setting the connection lease for each distinct scheme + host combination.

public class ServicePointManagingMessageHandler : HttpClientHandler
{
    private readonly ConcurrentDictionary&lt;Uri, ServicePoint&gt; _uriCache = new ConcurrentDictionary&lt;Uri, ServicePoint&gt;();
    private readonly int _oneMinuteInSeconds = (int)TimeSpan.FromMinutes(1).TotalSeconds;

    protected override Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.RequestUri.IsAbsoluteUri)
        {
            var baseUri = new Uri($"{request.RequestUri.Scheme}://{request.RequestUri.Host}");

            _uriCache.AddOrUpdate(baseUri, uri =&gt;
            {
                var sp = ServicePointManager.FindServicePoint(uri);
                sp.ConnectionLeaseTimeout = _oneMinuteInSeconds;

                return sp;
            }, (uri, point) =&gt; point);
        }

        return base.SendAsync(request, cancellationToken);
    }
}


Usage:

var client = new HttpClient(new ServicePointManagingMessageHandler());


I am wondering if the concept of intercepting the URI's as they come in to the HttpClient will allow the HttpClient to safely be used as a singleton without any of the issues listed in that article.

This gets around needing to know all hostnames that you might connect to at startup by intercepting calls - if people agree with this approach then it seems like it should become the accepted way to use the HttpClient for standard cases.
Just a few things:


You have already named the variable _oneMinuteInSeconds - I'd say you don't gain much by initializing it via a TimeSpan the way you do it. Just saying _oneMinuteInSeconds = 60 would be good enough since it's quite clear what the 60 stands for.
Actually, according to MSDN the ConnectionLeaseTimeout is set in milliseconds as such your code is of by a factor of 1000 regarding the timeout (why the framework designers have not consistently used TimeSpan everywhere is a bit of a mystery to me).