1

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 
3
  • what are the header values you send while making a request from Postman? I get a Bad Request error when I send the above-mentioned JSON to the endpoint via Postman. and what is var token = await _tokenService.RefreshToken();. Is it mandatory? and what is your intent by File(data, "application/octet-stream", "FeatureClass.Zip"); Commented Sep 8, 2017 at 7:29
  • Request headers updated. Ignore the tokenService. It is only used, to generate an authtoken to get the Json in the first place. That is why I provided a sample Json string. Commented Sep 8, 2017 at 7:35
  • Use telerik fiddler or similar to observe the messages on the wire and compare postman to c# outbound. Take special care over headers. Commented Sep 8, 2017 at 9:26

1 Answer 1

3

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); 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.