'HttpClient using FormUrlEncodedContent

I have checked other answers before posting this, so please try not to jump straight to conclusions here. I'm using HttpClient to connect to the API for an application we use, but it appears to not be recognising or finding one of the parameters it requires. The body just a custom object.

This initially didn't work in Postman, but when I changed the Content-Type and Body to 'x-www-form-urlencoded' I would receive a 200 response and the required information in return. Looking on here I hoped that switching from StringContent to FormUrlEncodedContent would help, but I still get the same end result.

Here is a cut down version of my code, I hope someone can help. Perhaps I've missed a step.

internal class API
{
    private static HttpResponseMessage Response;
    private static HttpClient Client;
    private static FormUrlEncodedContent UrlEncodedContent;
    private static Dictionary<string, string> bodyDictionary;

    internal static async Task<string> Invoke(string command, string 
name, object body = null, string method = "GET")
    {
        // Create HTTP Client
        Client = new HttpClient();
        Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        string url = "https://" + name + "/Application/" + command;

        switch(method)
        {
            case "POST":
                bodyDictionary = Convert.ConvertClassToDictionary(body); // no problem here. fully tested      
                UrlEncodedContent = new FormUrlEncodedContent(bodyDictionary);
                Post(url, UrlEncodedContent).Wait();
                UrlEncodedContent.Dispose();
                break;
        }

        return Response;
    }

    static private async Task Post(string url, FormUrlEncodedContent content)
    {
        Response = await Client.PostAsync(url, content);
    }
}

It works fine in powershell and is very simple, but it isn't an option here.

$uri = "https://application.com/application/token"
$headers = @{"Accept"="application/json"; "Content-Type"="application/x-www-form-urlencoded"}
$body = @{"username"="user";"password"="pass";"grant_type"="password";"client_id"="id12345"}
$response = Invoke-RestMethod -Method Post -Uri $uri -Body $body -Headers $headers


Solution 1:[1]

looks this! the method GetResponse. I send an HttpRequestMessage (Request property) filled with the information that you are putting in the HttpClient.

public void SetContent<TEntity>(TEntity input)
{
    var json = JsonConvert.SerializeObject(input);

    if (Request.Method == HttpMethod.Post || Request.Method == HttpMethod.Put)
    {
        if (string.IsNullOrEmpty(ContentType) || ContentType == "application/json")
        {
            Request.Content = new StringContent(json, Encoding.UTF8, "application/json");
        }
        else
        {
            var parameters = JsonConvert.DeserializeObject<Dictionary<string, string>>(json)
                                        .Concat(CustomParameters)
                                        .Where(p => !string.IsNullOrEmpty(p.Value));

            Request.Content = new FormUrlEncodedContent(parameters);
        }
    }
}

public Out GetResponse<TEntity, Out>(HttpClient client, TEntity input)
{
    var response = client.SendAsync(Request).Result;
    var content = response.Content.ReadAsStringAsync().Result;

    SetHttpClientDataToEntity(input, response);

    if (!response.IsSuccessStatusCode)
    {
        ErrorDetail error;

        throw content.TryParseJson(out error)
                    ? new Exception(error.Message)
                    : throw new Exception(content);
    }

    Out result;
    content.TryParseJson<Out>(out result);
    return result;
}

Solution 2:[2]

You're going to need to create an HttpRequestMessage instance so that you can add the "Content-Type" header to it and use the HttpClient.SendAsync overload that accepts an HttpRequestMessage instead of a Uri.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 agua from mars
Solution 2 Kyle Burns