【问题标题】:Custom header in HttpClient POST request not workingHttpClient POST 请求中的自定义标头不起作用
【发布时间】:2020-01-27 15:32:54
【问题描述】:

我在使用 HttpClient 时尝试发送 POST 请求。当我运行代码时,我得到了未经授权的响应。但我可以让它在 PostMan 中工作。下面是我当前的代码 sn-p 和我正在尝试执行的图片。我想补充一下,我正在尝试在我的身体中发送一个 json 字符串。

using (HttpClient client = new HttpClient())
        {
            var connectionUrl = "https://api.accusoft.com/prizmdoc/ViewingSession";
            var content = new Dictionary<string, string> { { "type", "upload" }, { "displayName", "testdoc" } };
            // Serialize our concrete class into a JSON String
            var stringPayload = JsonConvert.SerializeObject(content);

            // Wrap our JSON inside a StringContent which then can be used by the HttpClient class
            var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");

            using (var httpClient = new HttpClient())
            {
                //client.DefaultRequestHeaders.Add("Acs-Api-Key", "aPsmKCmvkZHf9VakCmfHB8COmzRxXY5FDhj8F1FU1IGmQlOkfjiKESKxfm38lhey");
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Acs-Api-Key", "aPsmKCmvkZHf9VakCmfHB8COmzRxXY5FDhj8F1FU1IGmQlOkfjiKESKxfm38lhey");

                // Do the actual request and await the response
                var httpResponse =  httpClient.PostAsync(connectionUrl, httpContent).Result;

                if (httpResponse.StatusCode == HttpStatusCode.OK)
                {
                    // Do something with response. Example get content:
                    var connectionContent = httpResponse.Content.ReadAsStringAsync().Result;

                }
                else
                {
                    // Handle a bad response
                    return;
                }
            }
        }

【问题讨论】:

  • 使用像 wireshark 或 fiddler 这样的嗅探器,比较 Postman 结果和 c# 结果之间的第一个请求标头。一个或多个标题不同。然后让 c# 应用程序头看起来和邮递员头完全一样。
  • 会不会是因为你的 api-key 的值太短了?即它很快就会过期
  • 不,api密钥不是随机生成的。它用于所有 api 调用

标签: c# httpwebrequest httpclient


【解决方案1】:

除了haldo的回答,

在您的代码中,您将Acs-Api-Key 标头添加为Authorization header,这意味着它最终看起来像Authorization: Acs-Api-Key (key) 而不是Acs-Api-Key: (key),这是您在PostMan 中所拥有的。

不要将其添加为授权标头,只需将其添加为常规标头即可。

client.DefaultRequestHeaders.Add("Acs-Api-Key","(key)");

还有其他可能导致问题的原因是您没有像在 PostMan 中那样将内容包装在“源”对象中。有几种方法可以做到这一点

第一种方法是简单地将其包装成字符串格式:

stringPayload = $"\"source\":{{{stringPayload}}}"

或者你可以在序列化之前通过制作自己的对象而不是字典来完成

var content = new PayloadObject(new Source("upload", "testdoc"));
var stringPayload = JsonConvert.SerializeObject(content);

// Send the request

class PayloadObject{
    Source source {get; set;}
    PayloadObject(Source source){
        this.source = source;
    }
}
class Source{
    string type {get; set;}
    string displayName {get; set;}
    Source(string type, string displayName){
        this.type = type;
        this.displayName = displayName;
    }
}

【讨论】:

  • 我不完全确定在代码中使用哪个标头,如您所见,我注释掉了您的建议。
  • 是的,我确实注意到了。我只是想澄清一下。 @haldo 的回答中提到了另一个问题。 您正在使用两个HttpClients,其中一个有您的标题,另一个没有。您正在使用没有标头的那个来发送请求。
  • 我也解决了这个问题。我认为这可能与源对象有关。我现在正在努力,看看它是否有效
  • 进行所有更改后,我现在得到一个错误“服务器提交了协议违规。Section=ResponseStatusLine”在对错误进行研究后,我在 web.config 中添加了一个段以将 useUnsafeHeaderParsing 设置为 true 并且它仍然不起作用。知道这里可能是什么问题吗?
【解决方案2】:

当您只需要使用一个时,您使用的是两个HttpClients。

using (HttpClient client = new HttpClient())

using (var httpClient = new HttpClient())

第二个 (httpClient) 正在发帖,但身份验证标头已添加到 client。只需删除第二个 (httpClient) 并确保使用 client.PostAsync(...) 发送请求。


我还考虑在发送请求时使用await,而不是.Result(看看为什么here):

var httpResponse = await client.PostAsync(connectionUrl, httpContent);

【讨论】:

  • 我修复了双 httpclient(s) 仍然有问题。我认为这可能是我试图发送它的来源。但感谢您指出明显的双重用法
猜你喜欢
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多