I am trying to conduct an HTTP call to another server from within an ASP.NET application run on IIS 8.5.
To get started, I took some hints from an article by Microsoft, Call a Web API From a .NET Client (C#). I could easily see a pattern of how they make HTTP calls there; to show just one shortened example:
static async Task<Product> GetProductAsync(string path)
{
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
// retrieve response payload
... = await response.Content.ReadAsAsync<...>();
}
// do something with data
}
Easy enough, I thought, so I quickly wrote a similar method for my application (note that the ReadAsAsync
extension method appears to require an additional library, so I chose one of the built-in, more abstract, but otherwise presumeably analogous methods):
private async Task<MyInfo> RetrieveMyInfoAsync(String url)
{
var response = await HttpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<MyInfo>(responseBody);
}
Unfortunately, calling this method will cause my application to hang. When debugging, it turns out that the await
call to GetAsync
never returns.
After searching around for a bit, I stumbled over a remotely similar issue, in whose comments section I found a very interesting suggestion by Mr. B:
Remove all the async stuff and make sure it works.
So I gave it a try:
private Task<MyInfo> RetrieveMyInfoAsync(String url)
{
return HttpClient.GetAsync(url).ContinueWith(response =>
{
response.Result.EnsureSuccessStatusCode();
return response.Result.Content.ReadAsStringAsync();
}).ContinueWith(str => JsonConvert.DeserializeObject<MyInfo>(str.Result.Result));
}
Somewhat surprisingly (to me), this works. GetAsync
returns the expected response from the other server within less than a second.
Now, working with AngularJS at the same time, I am a bit disappointed by things like response.Result.Content
and str.Result.Result
. In AngularJS, I'd expect the above call to be simply something like:
$http.get(url).then(function (response) {
return response.data;
});
Even if we discount the automatic JSON deserialization that's happening in JavaScript, the AngularJS code is still easier as e.g. response
is not wrapped into a promise or anything like that, nor will I end up with a structure like Task<Task<...>>
when returning another promise from within the continuation function.
Therefore, I am not very happy with having to use this ContinuesWith
syntax rather than the more readable async-await pattern, if the latter just worked.
What am I doing wrong in the async-await variant of my C# HTTP call?