Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpClient.PostAsJsonAsync never sees when the post is succeeding and responding

We are using an HttpClient to post json to a restful web service. In one instance, we are running into something that has us baffled. Using tools like postman, fiddler etc, we can post to an endpoint and see that it is working. When we do the same with HttpClient.PostAsJsonAsync, we can verify in the software we are posting to that it received the data just fine. However, our PostAsJsonAsync will always eventually time out rather than give us a response.

We have worked with the team that created the service we are consuming, plus our additional testing on our side, and we have not yet been able to truly time out that service.

Every time we do a post with HttpClient, we then can verify that the target software we post to does indeed get the data. Any time we do a post to that target software from any other tool, we always very quickly see a response with status code of 200. Something about HttpClient is failing to accept the response from this particular service. Does anyone have an idea what we can look at from here?

Here's the code (though it is so cookie cutter that I hardly feel it is needed)

public string PostData(string resourcePath, Object o, Boolean isCompleteUrl = false, int timeoutMinutes = -1)
    {
        using (var client = new HttpClient())
        {
            if (timeoutMinutes > 0)
            {
                client.Timeout = new TimeSpan(0,timeoutMinutes,0);
            }
            var useUrl = isCompleteUrl ? resourcePath : ApiBase + resourcePath;
            var response = client.PostAsJsonAsync(useUrl, o).Result;
            if(response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                return response.Content.ReadAsStringAsync().Result;
            }
            return "";
        }

    }
like image 623
Danny Avatar asked Jun 04 '15 20:06

Danny


1 Answers

This:

var response = client.PostAsJsonAsync(useUrl, o).Result;

Is causing you code to deadlock. This is often the case when blocking on async API's, and that's why you're experiencing the "I don't see any response coming back" effect.

How is this causing a deadlock? The fact that you are executing this request in an environment that contains a synchronization context, perhaps one which belongs to the UI. It's executing the async request, and when the response arrives, it continues via an IO completion thread which attempts to post the continuation onto that same UI context, which is currently blocked by your .Result call.

If you want to make an HTTP request synchronously, use WebClient instead. If you want to take advantage of the async API properly, then await instead of block with .Result.

like image 56
Yuval Itzchakov Avatar answered Oct 11 '22 03:10

Yuval Itzchakov