After reading this blog post and this official www.asp.net note:
HttpClient is designed to instantiate and reuse the life of the application. Especially in server applications, creating a new HttpClient instance for each request will exhaust the number of sockets available under heavy loads. This will result in a SocketException Error.
I found that our code deleted the HttpClient for each call. I am updating our code to reuse HttClient, but I am interested in implementation, but not in streaming mode.
Here is the current draft of the new code:
To test the modules, we used the shell for HttpClient, consumers call the shell:
public class HttpClientWrapper : IHttpClient { private readonly HttpClient _client; public Uri BaseAddress { get { return _client.BaseAddress; } set { _client.BaseAddress = value; } } public HttpRequestHeaders DefaultRequestHeaders { get { return _client.DefaultRequestHeaders; } } public HttpClientWrapper() { _client = new HttpClient(); } public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, String userOrProcessName) { IUnityContainer container = UnityCommon.GetContainer(); ILogService logService = container.Resolve<ILogService>(); logService.Log(ApplicationLogTypes.Debug, JsonConvert.SerializeObject(request), userOrProcessName); return _client.SendAsync(request); } #region IDisposable Support private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing && _client != null) { _client.Dispose(); } disposedValue = true; } } public void Dispose() { Dispose(true); } #endregion }
Here is the service that calls:
public class EnterpriseApiService : IEnterpriseApiService { private static IHttpClient _client; static EnterpriseApiService() { IUnityContainer container = UnityCommon.GetContainer(); IApplicationSettingService appSettingService = container.Resolve<IApplicationSettingService>(); _client = container.Resolve<IHttpClient>(); } public EnterpriseApiService() { } public Task<HttpResponseMessage> CallApiAsync(Uri uri, HttpMethod method, HttpContent content, HttpRequestHeaders requestHeaders, bool addJsonMimeAccept = true) { IUnityContainer container = UnityCommon.GetContainer(); HttpRequestMessage request; _client.BaseAddress = new Uri(uri.GetLeftPart(UriPartial.Authority)); if (addJsonMimeAccept) _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request = new HttpRequestMessage(method, uri.AbsoluteUri);
My questions:
- Is this a suitable approach for reusing an HttpClient object?
- Is the _httpClient static field (populated with a static constructor) common to all instances of EnterpriseApiService? I wanted to confirm, as called by instance methods.
- When CallApiAsync () is called, when it makes a change to the static HttpClient, for example, "_client.DefaultRequestHeaders.Accept.Add (new MediaTypeWithQualityHeaderValue (" application / json ")), can these values ββbe overwritten by another process before the last line of" _client. Is SendAsync called? I'm concerned that halfway through CallApiAsync () processing, the static instance is being updated.
- Since it calls SendAsync (), is the answer guaranteed to the correct answer? I want to confirm that the answer does not transfer to another subscriber.
Update: Since I deleted USING statements and the Garage Collection does not call Dispose, I'm going to move on to a safer approach to creating a new instance inside the method. To reuse an instance of HttpClient even during the life cycle of a stream, this will require significant processing of the logic, because the method sets the HttpClient properties for each call.