Creating a new HttpClient instance for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.
Don't use using statements. Because HttpClient instances should be long-lived. Disposing them forcibly closes the underlying TCP connection that is supposed to be pooled. If we share a single instance of HttpClient then we can reduce the waste of sockets by reusing them. Don't use ;
.Wait()
.Result
.GetAwaiter().GetResult() to avoid blocking.
You create a single static instance of HttpClient. In console or desktop applications, you can expose this instance just about anywhere. In an ASP.NET application, you can create it in the Global.asax.cs file.
If you have a manageable number of configurations, create an HttpClient instance for each one. You will be slightly less efficient than a single instance, but significantly more efficient than creating and disposing each time.
In this way, you can re-use the client instances as appropriate. Just set all the headers, base URLs, and ServicePointManager connection timeouts individually.
Global.asax.cs:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Optimization;
using System.Web.Routing;
namespace WebApplicationTestHttpClient
{
public class Global : HttpApplication
{
internal static HttpClient httpClientInstance1;
//internal static HttpClient httpClientInstance2;
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// 1
Uri baseUri1 = new Uri("https://api.domain1.com");
httpClientInstance1 = new HttpClient();
httpClientInstance1.BaseAddress = baseUri1;
httpClientInstance1.DefaultRequestHeaders.Clear();
httpClientInstance1.DefaultRequestHeaders.ConnectionClose = false;
httpClientInstance1.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
ServicePointManager.FindServicePoint(baseUri1).ConnectionLeaseTimeout = 60 * 1000;
// 2
//Uri baseUri2 = new Uri("http://api.domain2.com"); // /json_api/
//httpClientInstance2 = new HttpClient();
//httpClientInstance2.BaseAddress = baseUri2;
//httpClientInstance2.DefaultRequestHeaders.Clear();
//httpClientInstance2.DefaultRequestHeaders.ConnectionClose = false;
//httpClientInstance2.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
//ServicePointManager.FindServicePoint(baseUri2).ConnectionLeaseTimeout = 60 * 1000;
}
}
}
Basic Usage Example:
public async Task<string> Post1()
{
StringBuilder parameter = new StringBuilder();
parameter.Append("payload");
var content = new StringContent(parameter.ToString(), Encoding.UTF8, "application/xml");
var response = await Global.httpClientInstance1.PostAsync("/sms/send/xml", content);
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
return result;
}
Reference :
https://www.codeproject.com/Articles/1194406/Using-HttpClient-As-It-Was-Intended-Because-You-re
https://www.mytechramblings.com/posts/dotnet-httpclient-basic-usage-scenarios/
https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
https://stackoverflow.com/questions/18976042/httpclientfactory-create-vs-new-httpclient