async await for a HttpClient.PostAsync call

65.3k views Asked by At

I'm trying to wrap a call to PostAsync so I don't have to recode the call sequence all over my code base. The issue I'm having is the HttpResponseMessage I assigned from the call is not the same as the one the consumer of my method calls. Here is the code:

internal class RestHttpClient
{
    public HttpResponseMessage ResponseMessage = new HttpResponseMessage();

    public async void SendRequest(string adaptiveUri, string xmlRequest)
    {
        using (HttpClient httpClient = new HttpClient())
        {
            StringContent httpConent = new StringContent(xmlRequest, Encoding.UTF8);

            try
            {
                ResponseMessage = await httpClient.PostAsync(adaptiveUri, httpConent);
            }
            catch (Exception ex)
            {
                ResponseMessage.StatusCode = HttpStatusCode.InternalServerError;
                ResponseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", ex);
            }
        }
    }
}

And I'm trying to call the method as follows:

RestHttpClient restHttpClient = new RestHttpClient();

restHttpClient.SendRequest(adaptiveUri, xmlRequest);

return restHttpClient.ResponseMessage;

When I make the call the ResponseMessage object always contains an Ok status even if that is not what is actually returned from the PostAsync call.

1

There are 1 answers

8
Yuval Itzchakov On BEST ANSWER

The reason you're seeing this is because your method is async void which executes in a "fire and forget" fashion, so you're seeing the value returned by the instansiation of the response message, not the response of PostAsync.

Don't expose a single class HttpResponseMessage field, it may be stale if called concurrently on the same instance. Instead, return a new instance each time:

public async Task<HttpResponseMessage> SendRequestAsync(string adaptiveUri, string xmlRequest)
{
    using (HttpClient httpClient = new HttpClient())
    {
        StringContent httpConent = new StringContent(xmlRequest, Encoding.UTF8);

        HttpResponseMessage responseMessage = null;
        try
        {
             responseMessage = await httpClient.PostAsync(adaptiveUri, httpConent);
        }
        catch (Exception ex)
        {
            if (responseMessage == null)
            { 
                responseMessage = new HttpResponseMessage();
            }
            responseMessage.StatusCode = HttpStatusCode.InternalServerError;
            responseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", ex);
        }
        return responseMessage;
    }
}

And when you invoke it, properly await it:

return await restHttpClient.SendRequestAsync(adaptiveUri, xmlRequest);