Using C# HttpClient from Sync and Async code

The .NEt 4.5 C# System.Net.Http.HttpClient() is a very nice http client implementation, but can be tricky to use if you (like me) are not a trained asynchronous programming coder. So here is a quick cheat sheet on how to work around the Task<>, async and await methods when using the HttpClient().

UPDATE 2018-01-19: Removed the HttpClient from the Using clause to avoid having to instantiate a new HttpClient for every request, as this can lead to socket exhaustion. For more information, read this Improper Instantiation antipattern article from Sitecore.

EXAMPLE 1: HTTPCLIENT GET WITH RETURN VALUE:

THE GET METHOD:

private static readonly HttpClient _httpClient= new HttpClient();

public static async Task<string> Get(string queryString)
{
  string authUserName = "user";
  string authPassword = "password";
  string url = "https://someurl.com";

  // If you do not have basic authentication, you may skip these lines
  var authToken = Encoding.ASCII.GetBytes($"{authUserName}:{authPassword}");
  _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));

  // The actual Get method
  using (var result = await _httpClient.GetAsync($"{url}{queryString}"))
  {
    string content = await result.Content.ReadAsStringAsync();
    return content;
  }
}

THE USAGE:

// From synchronous code
string queryString = "?hello=world";
string result = Get(queryString).Result;

// From asynchronous code
string queryString = "?hello=world";
string result = await Get(queryString);

 

EXAMPLE 2: HTTPCLIENT PUT “FIRE-AND-FORGET” WITHOUT RETURN VALUE:

THE PUT METHOD:

private static readonly HttpClient _httpClient = new HttpClient();

public static async Task Put(string postData)
{
  string authUserName = "user";
  string authPassword = "password";
  string url = "https://someurl.com";
        
  // If you have no basic authentication, you can skip thses lines
  var authToken = Encoding.ASCII.GetBytes($"{authUserName}:{authPassword}");
  _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
    
  // The actual put method including error handling
  using(var content = new StringContent(postData))
  {
    var result = await _httpClient.PutAsync($"{url}", content);
    if (result.StatusCode == HttpStatusCode.OK)
    {
      return;
    }
    else
    {
      // Do something with the contents, like write the statuscode and
      // contents to a log file
      string resultContent = await result.Content.ReadAsStringAsync();
      // ... write to log
    }
  }
}

THE USAGE:

// You can call the method from asynchronous
// and it will actually run asynchronous. In this fire-and-forget 
// pattern, there is no need to wait for the answer
Put("data");

// ... but if you will wait, simply call ".Wait()":
Put("data").Wait();

MORE TO READ:

 

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, c#, General .NET and tagged , , . Bookmark the permalink.