ConnectionRequest JSON post works on Android/iOS simulator not on actual iOS

612 views
Skip to first unread message

Marc Widdowson

unread,
Oct 27, 2013, 4:56:53 AM10/27/13
to codenameone...@googlegroups.com
I am sending some information in JSON format to a Web API using a ConnectionRequest with setPost(true). The API should return the JSON to indicate success.

For test, I am sending a fixed JSON string. I print the string to a TextArea before sending, so I can see it is definitely the same string on each device.
And I am not changing my code in any way, just running it locally or sending it as Android and iOS Debug builds.

Apart from the JSON string, I am also setting the URL string and three property-value pairs (an application key string, an authorization string, and content-type=application/json) but these are hard-coded and, since I am not changing the code, they should be the same in every case.

On the iPhone simulator and on the Android version, it works fine. 

On an actual iPhone and on an iPad, it does not work. I can do a GET to the same Web API, but this POST request fails with "500: Internal server error". 

This does not make sense to me. If I am sending exactly the same request, how can the server tell the request has come from an iOS device and decide to throw an exception?

There seem to be two possibilities:

(1) The iOS device adds information or fails to add information or otherwise interferes with the POST request in a way that is different from Android and the iOS simulator, so even though I set up the request in exactly the same way, what gets sent is not exactly the same.
(2) The iOS client somehow interprets the JSON that the server sends back to indicate success as being an error message. 

Any suggestions as to what could possibly be different about the actual iOS compared to Android and the iOS simulator that is causing this failure? 

Marc Widdowson

unread,
Oct 27, 2013, 8:20:21 AM10/27/13
to codenameone...@googlegroups.com
Further to my own query, could it be a Permissions/Certification issue? 

Should I have requested push notifications or something like that when I specified the app's requested services? I only went for the default ones of in-app purchases and game center.

Shai Almog

unread,
Oct 27, 2013, 3:34:51 PM10/27/13
to codenameone...@googlegroups.com
No.
The underlying implementation is quite different and its very hard to tell what has failed without access to the server since 500 is a server error.

From experience I know that iOS requests have some issues:
They are always gzipped (its hard to disable that).
They are more sensitive to illegal characters and headers e.g. using | character in the URL worked on Android/SE/ME etc. but not on iOS.

Without a hint of what is happening in the server its hard for me to guide you further though.

Marc Widdowson

unread,
Oct 27, 2013, 6:47:29 PM10/27/13
to codenameone...@googlegroups.com
Thank you very much...I'll talk to the server people Monday and try to find out what they are seeing...hopefully they may be able to see what's going wrong

Marc Widdowson

unread,
Oct 28, 2013, 1:36:18 PM10/28/13
to codenameone...@googlegroups.com
I have now got details of the logs and the cause of the failure. To recap, the issue is that exactly the same POST request to a Web API works on Android and on the iOS simulator, but fails on actual iOS devices. 

The error generated by the server is that the content-type header is not set. This is despite the fact that my code certainly does set the content-type header. To be precise, the server says the "Content-Type" header is not set, whereas my original code used "content-type" in lower case (as stated by the API), but I have changed this now and tried multiple variations, as well as setting the content-type to both "application/json" and "application/json; charset = utf-8"...but none of this makes any difference.

So the question is, why does setHeader("content-type", "application/json") work on Android and the iOS simulator, but not on an actual iOS device, and what can I do about this?

Details are as follows. My code looks like this:

         ConnectionRequest r = new ConnectionRequest() {
            ...postResponse() and readResponse(InputStream input) methods omitted....

            protected void buildRequestBody(OutputStream os) throws IOException {
                os.write(json.getBytes("UTF-8")); //json contains the JSON string
            }
        };
        r.setUrl(urlString); //the web API address
        r.setPost(true);
        r.addRequestHeader("Application-Key", "...");
        r.addRequestHeader("Authorization", "...");
        r.addRequestHeader("content-type", "application/json");  //NB...the content-type *is* set, but this somehow does not get loaded
        InfiniteProgress prog = new InfiniteProgress();
        Dialog dlg = prog.showInifiniteBlocking();
        r.setDisposeOnCompletion(dlg);
        NetworkManager.getInstance().addToQueue(r);

The relevant parts of the server logs are as follows:

From a successful attempt from the iPhone simulator...

2013-10-28T13:45:54  PID[20272] Information Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
2013-10-28T13:45:54  PID[20272] Information Message='Action returned 'StatusCode: 201, ReasonPhrase: 'Created', Version: 1.1, Content: System.Net.Http.ObjectContent`1[[XXX.xxxxx.WebApi.Models.BaseCardModel, XXX.xxxxx WebApi, Version=0.7.0.0, Culture=neutral, PublicKeyToken=null]], Headers:
{
  Content-Type: application/json; charset=utf-8
}'', Operation=ReflectedHttpActionDescriptor.ExecuteAsync


From a failed attempt from the iPhone...

2013-10-28T13:44:57  PID[20272] Information Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
2013-10-28T13:44:57  PID[20272] Warning     Message='UserMessage='The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.'', Operation=FormatterParameterBinding.ExecuteBindingAsync, Status=415 (UnsupportedMediaType), Exception=System.Web.Http.HttpResponseException: Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.

Marc Widdowson

unread,
Oct 28, 2013, 2:08:54 PM10/28/13
to codenameone...@googlegroups.com
An update to this...I now have it working...

Instead of 

   setHeader("content-type", "json/application");

I changed it to

   setContentType("json/application");

The first call works on other platforms, including the iOS simulator, but not on actual iOS. For iOS, you need to do it the second way.

Shai Almog

unread,
Oct 29, 2013, 2:04:43 AM10/29/13
to codenameone...@googlegroups.com
We have a small bug there. There is a special case to solve this for iOS/Windows Phone both of which are "difficult" in this specific header. However, the workaround was implemented incorrectly.
This will be fixed for the next server update.

Marc Widdowson

unread,
Oct 29, 2013, 5:28:18 AM10/29/13
to codenameone...@googlegroups.com
Thank you very much.
Reply all
Reply to author
Forward
0 new messages