【问题标题】:HttpClient using FormUrlEncodedContentHttpClient 使用 FormUrlEncodedContent
【发布时间】:2019-09-06 18:55:57
【问题描述】:

在发布之前我已经检查了其他答案,所以请尽量不要在这里直接下结论。我正在使用 HttpClient 连接到我们使用的应用程序的 API,但它似乎无法识别或找到它所需的参数之一。 body 只是一个自定义对象。

这最初在 Postman 中不起作用,但是当我将 Content-Type 和 Body 更改为“x-www-form-urlencoded”时,我会收到 200 响应和所需的信息作为回报。查看here 我希望从 StringContent 切换到 FormUrlEncodedContent 会有所帮助,但我仍然得到相同的最终结果。

这是我的代码的精简版,希望有人能提供帮助。也许我错过了一步。

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);
    }
}

它在 powershell 中运行良好并且非常简单,但这里不是一个选项。

$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

【问题讨论】:

    标签: c# dotnet-httpclient


    【解决方案1】:

    您将需要创建一个 HttpRequestMessage 实例,以便向其添加“Content-Type”标头并使用接受 HttpRequestMessage 而不是 Uri 的 HttpClient.SendAsync 重载。

    【讨论】:

    • 嗨凯尔。感谢您的答复。您需要在此处添加 Content-Type 标头吗?我的印象是 FormUrlEncodedContent 为你做的?当我早些时候从我链接的答案中尝试这个时,我可以看到标题,但仍然没有通过 HttpRequestMessage 获得所需的结果。我会在星期一早上再试一次。
    【解决方案2】:

    看起来这个! GetResponse 方法。我发送一个 HttpRequestMessage(请求属性),其中包含您在 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;
            }
    

    【讨论】:

    • 嗨维森特。谢谢你的回复。我不确定我是否完全理解您的回答,对此我还有些陌生,但我会在星期一早上看看。
    • 好的!我给你一个建议,不要在这样的场景中使用静态类。因为您的课程将与整个应用程序共享 httpclient 的实例,您可能会收到“网络”错误。
    • 维森特,谢谢。这个例子真的帮助了我,我现在收到了我的回复。值得注意的是,Kyle 的回答也是正确的,但我也需要使用 DeserializeObject 方法才能最终为我工作。显然我发送的密钥名称不正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多