使用HttpClient将JSON发布到端点时的常量BadRequest

时间:2017-09-08 06:21:37

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

我很难使用一个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");

构建字符串内容raw:

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

1 个答案:

答案 0 :(得分:2)

最后,我只是使用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);