Search code examples
c#dotnet-httpclientsendasync

SendAsync() returning 422 Unprocessable Entity


I wrote a function using GetAsync() which works fine, but now i'd like to expand on it using SendAsync() instead [for POSTing and sofourth]; however my SendAsync() version is not working as expected, it returns a 422 unprocessible entity. (no IDE atm; sorry for minor typos)

init

var Client = new HttpClient{
    BaseAddress = "https://example.com"
}
Client.DefaultRequestHeaders.UserAgent.ParseAdd("Project/1.0 (blah blah)");

...

Working GetAsync()

public async Task<string> GetResponse(string user, string pass){
    var uri = $"/user/login.json?name={user}&password={pass}";
    var req = await Client.GetAsync(uri);
    return req.Content.Request.Content.ReasStringAsync();
}

non working SendAsync()

public async Task<string> GetResponse(string page, Dictionary<string, string> args){
//assume page = "/user/login.json" and args == {"username", "user"},{"password", "pass"}
try{
    var req = new HttpRequestMessage
    {
        Method = HttpMethod.Get,
        RequestUri = new Uri(page),
        Content = new FormUrlEncodedContent(args),
    }

    var response = await Client.SendAsync(req);
    if(response.IsSuccessStatusCode){
        return await response.Content.ReasStringAsync();
    return null;
}
catch{ return null }
}

note: along with the 422, the response still contains json which states "invalid Auth Token!"

What is GetAsync() doing that SendAsync() is not?


Solution

  • Your Send included content in the BODY of a HTTP GET request.

    HTTP GET requests should not have a BODY and there are servers that wont process such requests.

    Convert the dictionary to a QueryString and include it in the URI.

    public async Task<string> GetResponse(string page, Dictionary<string, string> args) {
        //assume page = "/user/login.json" and args == {"username", "user"},{"password", "pass"}
        try {
            QueryString queryString = QueryString.Create(args);
            var uri = new Uri(page + queryString.ToString());
            var request = new HttpRequestMessage(HttpMethod.Get, uri);
            var response = await Client.SendAsync(request);
            if(response.IsSuccessStatusCode){
                return await response.Content.ReadAsStringAsync();
            return string.Empty;
        } catch { return string.Empty; }
    }