Reputation: 23945
I am struggeling to consume an API endpoint (http://ogre.adc4gis.com/convertJson) that takes JSON data and returns a zip file. Visiting http://ogre.adc4gis.com shows the parameters the api expects.
It absolutely works using Postman and using Javascript, so I am wondering what I am doing wrong with in my c# code.
This an example JSON string, which can be posted to the 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
}
}]
}
For completenes sake, this is the action method, that invokes the call to the bespoke 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;
}
Here comes the part where the actual call to the api is made. Payload is the escaped json string. The get rid of all the escapes, I've just converted it to an object and then back again.
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");
}
}
Every call returns an Error 400 Bad Request:
{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
}}
Things I've tried:
Do not convert the payload to an object and just use it as it is:
var pairs = new Dictionary<string, string>
{
{ "json", payload }
};
var json = JsonConvert.SerializeObject(pairs);
var content = new StringContent(json, Encoding.UTF8, "application/json");
Build the string content raw:
payload = "{ \"json\": " + payload + "}";
Use "application/x-www-url-formencoded" as Content-Type
I am a total loss here. What am I doing wrong?
EDIT As requested, here are the request headers from a successfull postman request:
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
Upvotes: 1
Views: 6736
Reputation: 23945
In the end I simply rebuild the payload from the website itself using Fiddler to capture it in the first place and it worked.
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);
Upvotes: 3