I've been working in ASP.NET Web API where I bumped into some weird interactions when trying to call another API. I've tried 3 different ways to use HttpClient, all with different results.
Have tested everything using Postman, hence some results.
private static string GetAPI(string url)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
HttpResponseMessage response = client.GetAsync(url).Result;
string contents = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
return contents;
}
}
return null;
}
Does work, but I want to use async
private static async Task<string> GetAPI(string url)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
HttpResponseMessage response = await client.GetAsync(url);
string contents = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
return contents;
}
}
return null;
}
Does not work. Will not go beyond the line HttpResponseMessage response = await client.GetAsync(url);
, since there's never a response?
private static readonly HttpClient client = new HttpClient();
private static async Task<string> GetAPI(string url)
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
HttpResponseMessage response = await client.GetAsync(url);
string contents = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
return contents;
}
return null;
}
Does work once. Will then throw the error:
System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: This instance has already started one or more requests. Properties can only be modified before sending the first request.
(as suggested by this SO answer).
I would appreciate it if someone could explain why these results are so different and/or give an alternative way to make a basic HttpClient
call (still would like to use async
).
@Igor has informed me about the deadlock issue in my second example.
So I currently used the HttpClient
as such (async
):
private static async Task<string> GetAPI(string url)
{
// TODO: Use a shared instance of HttpClient
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
var jsonString = await client.GetStringAsync(url).ConfigureAwait(false);
return jsonString;
}
}
While some things have been made clear, the entire question hasn't been answered yet. I therefore won't accept this as an answer, yet like to thank those for providing me good information on the use of HttpClient
.