Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async await for a HttpClient.PostAsync call

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.

like image 369
EricR Avatar asked Jun 15 '15 18:06

EricR


1 Answers

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);
like image 189
Yuval Itzchakov Avatar answered Sep 27 '22 16:09

Yuval Itzchakov