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:
- Asynchronous Programming with Async and Await from Microsoft
- Async and Await by Stephen Cleary
- You’re using httpclient wrong and it is destabilizing your software by Simon Timms
- WebClient vs HttpClient vs HttpWebRequest by The Geeko Gecko
Pingback: c# Async fire and forget | Brian Pedersen's Sitecore and .NET Blog
Pingback: HttpClient POST or PUT Json with content type application/json | Brian Pedersen's Sitecore and .NET Blog
Pingback: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the ‘await’ operator to the result of the call | Brian Pedersen's Sitecore and .NET Blog
Pingback: Add a UserAgent to the IHttpClientFactory in .NET Core | Brian Pedersen's Sitecore and .NET Blog
Pingback: HttpClient retry on HTTP timeout with Polly and IHttpClientBuilder | Brian Pedersen's Sitecore and .NET Blog
Pingback: C# get results from Task.WhenAll | Brian Pedersen's Sitecore and .NET Blog
Pingback: HttpClient follow 302 redirects with .NET Core | Brian Pedersen's Sitecore and .NET Blog
Your clear example on the use of the async method with synchronous code was a life saver. I have been seeking the solution to getting this to work for way too many hours. Thank you for the clear examples.
LikeLike
Pingback: C# HttpClient and IHttpClientFactory in .net core | Brian Pedersen's Sitecore and .NET Blog