Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between HttpClient PostAsync and SendAsync

Working on a project where a WPF front end, and trying to get a handle on async calls to HttpClient and I've been going around and around trying to get PostAsync to work, but it routinely appears to deadlock, or at least the post response times out, even with large values for timeout, and a visible response in fiddler.

So, after a while I decided to try out a few other methods on HttpClient, and they worked, first try. No idea why.

I'm clean all the way to my WPF button with awaits, asyncs, and .ConfigureAwait(false) (I think):

Button:

private async void Generate_Suite_BTN_Click(object sender, RoutedEventArgs e)
{
    await suiteBuilder.SendStarWs().ConfigureAwait(false);
}

XmlDoc Load:

internal async Task SendStarWs()
{
    var xmlDoc = new XmlDocument();
    xmlDoc.Load("C:\\Temp\\file.xml");
    await StarWSClient.SendStarMessage(xmlDoc).ConfigureAwait(false);
}

SendMessage:

private static readonly HttpClient Client = new HttpClient {MaxResponseContentBufferSize = 1000000};

public static async Task<STARResult> SendMessage(vars)
{
var response = await SendRequestAsync(url, contentNew, Client).ConfigureAwait(false);
return new STARResult(response, hash);
}

This call '500s' against my endpoint immediately, which I'd expect:

var response = await SendRequestAsync(url, contentNew, Client).ConfigureAwait(false);

private static async Task<HttpResponseMessage> SendRequestAsync(string adaptiveUri, StringContent content, HttpClient httpClient)
{
    HttpResponseMessage responseMessage = null;
    try
    {
        responseMessage = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, adaptiveUri)).ConfigureAwait(false);
    }
    catch (Exception ex)
    {
        if (responseMessage == null)
            responseMessage = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.InternalServerError,
                ReasonPhrase = $"SendRequestAsync failed: {ex.Message}"
            };
    }
    return responseMessage;
}

The Post variant returns a TaskCancellationException, with timeout message regardless of timeout value:

var response = await PostRequestAsync(url, contentNew, Client).ConfigureAwait(false);

private static async Task<HttpResponseMessage> PostRequestAsync(string adaptiveUri, StringContent content, HttpClient httpClient)
{
    HttpResponseMessage responseMessage = null;
    try
    {
        responseMessage = await httpClient.PostAsync(adaptiveUri, content).ConfigureAwait(false);
    }
    catch (Exception ex)
    {
        if (responseMessage == null)
            responseMessage = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.InternalServerError,
                ReasonPhrase = $"PostRequestAsync failed: {ex.Message}"
            };
    }
    return responseMessage;
}

My endpoint responds normally to our other software, so I'm pretty sure the endpoint is solid, I can't fathom why the post response is blocked, when the send isn't.

like image 827
Ian Moriarty Avatar asked Mar 07 '18 01:03

Ian Moriarty


1 Answers

SendAsync can make any http verb request depending on how you set that property. PostAsync and similar are just convenience methods. Those convenience methods use SendAsync internally which is why when you derive a handler you only need to override SendAsync and not all of the send methods.

To your other question though: When you use SendAsync you need to create the content and pass it. Your only sending an empty message. The 500 likely means that the api got null from the model binding and kicked you back. Just as @John commented.

like image 120
JSteward Avatar answered Oct 03 '22 08:10

JSteward