0

Im in the process of creating a base class for typed HttpClient services (yes, I'm utilizing IHttpClientFactory). I wrote the process in such a way that for each CRUD method invoked from the service, the first thing said service does is check for and assign an access token to attach to the HttpClient header. Example:

public abstract class BaseNetworkService : IBaseNetworkService {
 protected HttpClient _httpClient { get; }
 public BaseNetworkService(HttpClient client, ...) {
 _httpClient = client;
 }
 
 public async Task<T> GetAsync<T>(string extendedUrl, ICacheContext cacheContext = null) {
 ... check Redis Cache, return result if there ...
 
 Http client = GetcurrentAccessToken(_httpClient);
 var response = await client.GetAsync(extendedUrl);
 ...
 }
}

I'll admit upfront that I am not entirely sure why I have always made my HttpClients readonly and upon Googling for answers, it's probably because every document and guide on HttpClient with dependency injection makes the client readonly. I didn't find any material explaining the reason for that.

With that in mind, should your HttpClientremain readonly? Should any customization, such as attaching an access token, be done in the classes constructor?

asked Nov 14, 2020 at 0:48
1
  • 6
    The readonly keyword does not prevent you from mutating the client. It prevents you from replacing the client. Commented Nov 14, 2020 at 0:57

1 Answer 1

3

The readonly keyword does not prevent mutability of an object. It only makes sure that you do not replace it by doing myReadonlyObject = new Object().

As for why your HttpClient is readonly - because there is no need to ever replace it with a new HttpClient. In fact, in case of HttpClient, you should be aiming to reuse it, instead of creating a new client for each web request. That is how HttpClient was designed to be used.

The reason for that is, that even after your request went through, you got the response and the connection was closed, the underlying socket still stays open and listens for any packets that might have been delayed in the network traffic. This is obviously not a huge deal if the application only makes a couple of requests and is done. However it might become a bigger issue when we make tens of thousands requests in relatively short amount of time and use a new instance of HttpClient for each request, since the amount of sockets that can be open at once is limited by the OS.

answered Nov 14, 2020 at 18:24
9
  • ` Http client = GetcurrentAccessToken(_httpClient);` So this would leave an underlying socket open? Commented Nov 15, 2020 at 19:08
  • @8protons Yes, for a while. In Windows it's around 4 minutes. So ideally you would not create new HttpClients, and instead reuse one instance of it throughout the whole application run time to avoid having too many open sockets. Commented Nov 15, 2020 at 20:32
  • Just to add to this, HttpClient is an awful footgun as this excellent blog post from 2016 shows ( aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong ). Ive personally seen this happen in production, and it is awful to troubleshoot. Always reuse one instance of it if you use it. Or use some of the other http client libraries on .net that doesnt have this awful design built in. Commented Nov 16, 2020 at 7:07
  • @Aleksander Are you sure? Because the initial http client is managed watched by IHttpClientFactory. When I created a new instance and closed the original, the clone seemed to close as well. Commented Nov 16, 2020 at 17:43
  • @8protons How and where are you creating a new instance? Commented Nov 16, 2020 at 18:18

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.