【问题标题】:Constant BadRequest when posting JSON to endpoint using HttpClient使用 HttpClient 将 JSON 发布到端点时出现常量 BadRequest
【发布时间】:2017-09-08 06:21:36
【问题描述】:

我正在努力使用一个 API 端点 (http://ogre.adc4gis.com/convertJson),它接受 JSON 数据并返回一个 zip 文件。访问http://ogre.adc4gis.com 会显示 api 期望的参数。

它绝对可以使用 Postman 和 Javascript,所以我想知道我在 c# 代码中做错了什么。

这是一个示例 JSON 字符串,可以发布到 API:

{
    "displayFieldName": "NUM_GES2_1",
    "fieldAliases": {
        "NUM_GES2_1": "NUM_GES2_1"
    },
    "geometryType": "esriGeometryPoint",
    "spatialReference": {
        "wkid": 102362,
        "latestWkid": 4647
    },
    "fields": [{
        "name": "NUM_GES2_1",
        "type": "esriFieldTypeString",
        "alias": "NUM_GES2_1",
        "length": 254
    }],
    "features": [{
        "attributes": {
            "NUM_GES2_1": "001-08"
        },
        "geometry": {
            "x": 32674408.2009,
            "y": 5790291.4659000002
        }
    }]
}

为了完整起见,这是调用定制 api 的操作方法:

[HttpGet]
[Route("{id:int}/Attributive")]
public async Task<IActionResult> GetFeatureClass(int id)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    //get token from internal api
    var token = await _tokenService.RefreshToken();
    //dummy address that returns a single object for development
    var tokenObjString = await client.GetStringAsync(
        $"http://url.to/MapServer/{id}/query?where=1%3D1&objectIds=4&f=pjson&token={token}"
    );

    var data = await PostDataToOgrService(tokenObjString);

    var response = File(data, "application/octet-stream", "FeatureClass.Zip");
    return response;
}

这里是对 api 进行实际调用的部分。 Payload 是转义的 json 字符串。摆脱所有的转义,我刚刚将它转换为一个对象,然后再返回。

public async Task<byte[]> PostDataToOgrService(string payload)
{
    var client = new HttpClient();
    var newJson = JsonConvert.DeserializeObject(payload);
    var pairs = new Dictionary<string, object>
    {
        { "json", newJson }
    };
    var json = JsonConvert.SerializeObject(pairs);
    var content = new StringContent(json, Encoding.UTF8, "application/json");

    var response = await client.PostAsync("http://ogre.adc4gis.com/convertJson", content);

    if (response.IsSuccessStatusCode)
    {
        return await response.Content.ReadAsByteArrayAsync();
    }
    else
    {
        throw new Exception("Something went wrong");
    }
}

每次调用都会返回错误 400 错误请求:

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.NoWriteNoSeekStreamContent, Headers:
{
  Date: Fri, 08 Sep 2017 06:15:01 GMT
  ETag: W/"27-Ag3Jnk3T/v6dECAccJTzg4aO/wA"
  X-Powered-By: Express
  Access-Control-Allow-Origin: *
  Access-Control-Allow-Methods: POST
  Access-Control-Allow-Headers: X-Requested-With
  Access-Control-Expose-Headers: Content-Disposition
  Content-Length: 39
  Content-Type: application/json; charset=utf-8
}}

我尝试过的事情:

不要将有效负载转换为对象,直接使用它:

var pairs = new Dictionary<string, string>
{
    { "json", payload }
};
var json = JsonConvert.SerializeObject(pairs);
var content = new StringContent(json, Encoding.UTF8, "application/json");

构建原始字符串内容:

payload = "{ \"json\": " + payload + "}";

使用“application/x-www-url-formencoded”作为Content-Type

我在这里完全失去了。我做错了什么?

编辑 根据要求,以下是来自成功邮递员请求的请求标头:

POST /convertJson HTTP/1.1
cache-control: no-cache
Postman-Token: 2976abca-6725-43ce-873e-907c12a9fdee
Content-Type: multipart/form-data; boundary=--------------------------829328978588990941765750
User-Agent: PostmanRuntime/6.1.6
Accept: */*
Host: ogre.adc4gis.com
accept-encoding: gzip, deflate
content-length: 629
Connection: keep-alive

【问题讨论】:

  • 在从 Postman 发出请求时发送的标头值是什么?当我通过 Postman 将上述 JSON 发送到端点时,我收到 Bad Request 错误。什么是var token = await _tokenService.RefreshToken();。它是强制性的吗? File(data, "application/octet-stream", "FeatureClass.Zip"); 你的意图是什么
  • 请求标头已更新。忽略令牌服务。它仅用于生成 authtoken 以首先获取 Json。这就是为什么我提供了一个示例 Json 字符串。
  • 使用 Telerik fiddler 或类似工具观察线路上的消息,并将 postman 与 c# outbound 进行比较。请特别注意标题。

标签: c# json post asp.net-core httpclient


【解决方案1】:

最后,我只是使用 Fiddler 从网站本身重建了有效负载,以首先捕获它并且它起作用了。

var contentString = "json=" + System.Web.HttpUtility.UrlEncode(JsonConvert.SerializeObject(newJson));
var content = new StringContent(contentString, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await client.PostAsync("http://ogre.adc4gis.com/convertJson", content);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 2018-04-02
    • 1970-01-01
    • 2016-05-07
    • 2019-01-31
    • 1970-01-01
    相关资源
    最近更新 更多