16

I'm using HttpClient to make request to WebApi.

I have written this code

 public async Task<string> ExecuteGetHttp(string url, Dictionary<string, string> headers = null)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                }
                var response = await client.GetAsync(url);
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            } 
        }

Now I'm calling this method from my action.

public async Task<ActionResult> Index()
        {
            try
            {
                RestWebRequest RestWebRequest = new RestWebRequest();
                Dictionary<string, string> headers = new Dictionary<string, string>();
                headers.Add("Authorization", "bearer _AxE9GWUO__8iIGS8stK1GrXuCXuz0xJ8Ba_nR1W2AhhOWy9r98e2_YquUmjFsAv1RcI94ROKEbiEjFVGmoiqmUU7qB5_Rjw1Z3FWMtzEc8BeM60WuIuF2fx_Y2FNTE_6XRhXce75MNf4-i0HbygnClzqDdrdG_B0hK6u2H7rtpBFV0BYZIUqFuJpkg4Aus85P8_Rd2KTCC5o6mHPiGxRl_yGFFTTL4_GvSuBQH39RoMqNj94A84KlE0hm99Yk-8jY6AKdxGRoEhtW_Ddow9FKWiViSuetcegzs_YWiPMN6kBFhY401ON_M_aH067ciIu6nZ7TiIkD5GHgndMvF-dYt3nAD95uLaqX6t8MS-WS2E80h7_AuaN5JZMOEOJCUi7z3zWMD2MoSwDtiB644XdmQ5DcJUXy_lli3KKaXgArJzKj85BWTAQ8xGXz3PyVo6W8swRaY5ojfnPUmUibm4A2lkRUvu7mHLGExgZ9rOsW_BbCDJq6LlYHM1BnAQ_W6LAE5P-DxMNZj7PNmEP1LKptr2RWwYt17JPRdN27OcSvZZdam6YMlBW00Dz2T2dgWqv7LvKpVhMpOtjOSdMhDzWEcf6yqr4ldVUszCQrPfjfBBtUdN_5nqcpiWlPx3JTkx438i08Ni8ph3gDQQvl3YL5psDcdwh0-QtNjEAGvBdQCwABvkbUhnIQQo_vwA68ITg07sEYgCl7Sql5IV7bD_x-yrlHyaVNtCn9C4zVr5ALIfj0YCuCyF_l1Z1MTRE7nb");
                var getCategories = await RestWebRequest.ExecuteGetHttp("http://localhost:53646/api/Job/GetAllCategories?isIncludeChild=true", headers);
            }
            catch (HttpRequestException ex)
            {
                return View();
            }
  return View();
  }

Now It is said that HttpClient has been designed to be re-used for multiple calls.

How Can I use same httpClient object for multiple calls.

Let's suppose First I'm calling

http://localhost:53646/api/Job/GetAllCategories?isIncludeChild=true

Now In same controller I have to call another Api with diffrent header and diffrent url.

http://localhost:53646/api/Job/category/10

Should I make the global object of HttpClient and Use the same object for all API calls.

3
  • "Should I make the global object of HttpClient and Use the same object for all API calls." I believe so. Can you think of any specific reason that you could not store it globally and reuse it for all calls? Commented May 11, 2016 at 9:35
  • 1
    Check out this blog post of mine (literally about HttpClient best practices in .NET Core): bytedev.medium.com/… Commented Sep 23, 2021 at 2:08
  • 1
    Check this article as well thecodebuzz.com/… Commented Dec 10, 2021 at 6:53

3 Answers 3

14

The challenge in using just one HttpClient across your application is when you want to use different credentials or you try to vary the default headers for your requests (or anything in the HttpClientHandler passed in). In this case you will need a set of purpose specific HttpClients to re-use since using just one will be problematic.

I suggest creating a HttpClient per the "type" of request you wish to make and re-use those. E.g. one for each credential you need - and maybe if you have a few sets of default headers, one per each of those.

It can be a bit of a juggling act between the HttpClient properties (which are not thread safe) and need their own instance if being varied:

- BaseAddress
- DefaultRequestHeaders
- MaxResponseContentBufferSize
- Timeout

And what you can pass in to the "VERB" methods (get, put, post etc). For example, using HttpClient.PostAsync Method (String, HttpContent) you can specify your headers for the [HttpContent][3] (and not have to put them in the HttpClient DefaultHeaders).

All of the Async methods off the HttpClient are thread safe (PostAsync) etc.

Sign up to request clarification or add additional context in comments.

1 Comment

What about creating HttpRequestMessage for each request? And then use the SendAsync method of HttpClient. That way you can specify different credentials between requests, and still re-use the same HttpClient.
8

Just because you can, doesn't mean you should.

You don't have to, but you can reuse the HttpClient, for example when you want to issue many HTTP requests in a tight loop. This saves a tiny fraction of time it takes to instantiate the object.

Your MVC controller is instantiated for every request. So it won't harm any significant amount of time to instantiate a HttpClient at the same time. Remember you're going to issue an HTTP request with it, which will take many orders more time than the instantiation ever will.

If you do insist you want to reuse one instance, because you have benchmarked it and evaluated the instantiation of HttpClient to be your greatest bottleneck, then you can take a look at dependency injection and inject a single instance into every controller that needs it.

8 Comments

Good point in that you need to consider your use case. If you need the utmost maximum performance or have concerns about the number of connections open, then sharing HttpClients will benefit. When using DI, be careful not to resolve for every call or your DI overhead may negate any benefit.
@Murray HttpClient uses connection pooling.
To clarify, every HttpClient instance uses its own connection pool.
Not only performance, but also stability and reliability of your application should be considered. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong gives a good explanation of this.
@Larry you're absolutely right, I've learnt about the problems with HttpClient after writing this answer. I'll update it when I can.
|
6

in .net core you can do the same with HttpClientFactory something like this:

public interface IBuyService
{
    Task<Buy> GetBuyItems();
}

public class BuyService: IBuyService
{
    private readonly HttpClient _httpClient;

    public BuyService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<Buy> GetBuyItems()
    {
        var uri = "Uri";

        var responseString = await _httpClient.GetStringAsync(uri);

        var buy = JsonConvert.DeserializeObject<Buy>(responseString);
        return buy;
    }
}

ConfigureServices

services.AddHttpClient<IBuyService, BuyService>(client =>
{
     client.BaseAddress = new Uri(Configuration["BaseUrl"]);
});

documentation and example at here and here

Comments

Your Answer

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.