1

I have been provided with a REST service from my customer for which I should get JSON response for my iOS code.I am using content-type as "application/json" but somehow it is taken as "text/html" by default. I cross checked this in a REST client in my Mozilla browser using "application/json" for the content-type in header section and I could see the proper response.On using the below code, I am getting a 400 error from the server. I could always see "text/html" as being used as part of the 400 response by default

NSString * strBodyOnlineStart = [NSString stringWithFormat:@"&email=***@***.com&deviceCode=*****&password_value=***"];

      NSURL *urlOnlineStart = [NSURL
                          URLWithString:@"http://local.server/xxxxx"];
        NSMutableURLRequest *requestOnlineStart = [NSMutableURLRequest
                                                   requestWithURL:urlOnlineStart];


        [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

        [requestOnlineStart setHTTPMethod:@"POST"];
        NSData *requestBodyOnlineStart = [strBodyOnlineStart
                                          dataUsingEncoding:NSUTF8StringEncoding];
        [requestOnlineStart setHTTPBody:requestBodyOnlineStart];

Below is the response which I am getting from the server

Grey_Code
  • 454
  • 1
  • 4
  • 20
Leo Joseph
  • 69
  • 1
  • 1
  • 8
  • 1
    Try changing "application/json" to "application/json; charset=utf-8" and try encoding your request body wtih NSUTF8StringEncoding – startswithaj Apr 26 '14 at 11:44
  • Why are you using NSUTF32StringEncoding string encoding? Did you try to use NSUTF8StringEncoding? – Vlad Papko Apr 26 '14 at 11:46
  • by adding application/json; charset=utf-8 I still got the response(content-type text/html, status code 400). and @Visput Its nsutf8encoding only. I typed it by mistake – Leo Joseph Apr 26 '14 at 12:03
  • The ASP webservice is not encoding a json response before sending it. Check the API again – Malloc Apr 26 '14 at 12:03
  • Which API? is it the iOS code API or the server API? and the response is coming correctly in Firefox REST client @Malloc – Leo Joseph Apr 26 '14 at 12:07
  • If possible, try to request the `ASP.net API` directly from your browser and see whether it's returning a VALID json response. If yes, then check your encoded request. check this similar post: http://stackoverflow.com/a/7981511/602257 – Malloc Apr 26 '14 at 12:12
  • Since its a POST method, I tried using the REST client and I am getting the correct JSON response. Also I implemented the code from that link which you mentioned. Still the same response. @Malloc – Leo Joseph Apr 26 '14 at 12:23
  • I've solved this sort of thing many times in the past. It doesnt sound like every bit of the implementation is being talked about. Could be another header field that the rest client and browser are submitting that isnt in the ObjC code above. It would help to see an entire working request/response headers and body example from the rest client. By the way... Charles proxy and fiddler are excellent tools to solve this sort of thing! – Tom Pace Apr 26 '14 at 13:28
  • As I understand that fiddler is for windows, can you please provide its download link for mac osx ? Also in REST client(Firefox) we are only sending the content-type as "application/json" @TomPace – Leo Joseph Apr 26 '14 at 13:46
  • @LeoJoseph I had to buy the best mac-equivalent fiddler app, it is Charles proxy. I cannot remember if it has a free trial. Check my new posted answer for suggestion for content type vs body format. – Tom Pace Apr 26 '14 at 13:51

2 Answers2

2

I have built many server REST services and many mobile client apps to access them and run into issues like this countless times. So I know your pain, and I've solved these problems with my own set of tools (I like Fiddler on Windows and Charles on Mac) and learned many reasons for failures.

First observation:

Without the full details of a working request & response pair, and a failing request & response pair, finding the official solution isn't possible. But I'm pretty sure if you provided those, the official solution would be simple.

Testing

To test your problem, I installed REST client in Firefox and setup a new service on my development machine. Also, I used Charles Proxy on OS X with the edit request function to customize a raw request.

I cross checked this in a REST client in my Mozilla browser using "application/json" for the content-type in header section and I could see the proper response.

Odd that you say it worked. I tried that and the server failed to parse the body values. The server-side platform I'm using isn't ASP.NET, yet I'm just going on the standard expected behaviour of any platform. Possibly your REST client was not actually submitting the header. I wonder if you switched the header to some arbitrary value like application/notjson and see if it works still (then I'd assume it was the REST client overriding).

Probable cause

As given in the quote above, you give the impression of wanting to receive application/json in the response Content-Type header, and it seems you think you must send the Content-Type header in the request to match that response. That should not be necessary. The server should be able to receive your request in a standard format as application/x-www-form-urlencoded, that is typical of servers, and respond with JSON as you're expecting.

Usually, web servers do not naturally accept json as a request body format, and similarly, they usually do not receive incoming request Content-Type of application/json. But, I've seen cases where they do.

In any case, submitting a request with conflicting Content-Type and body formats is definitely a failing setup.

I found my server test responding with JSON, using your &email=***@***.com&deviceCode=*****&password_value=*** body, after switching the header to application/x-www-form-urlencoded, application/json. Typical goodness.

Code

Try commenting-out the following line:

    [requestOnlineStart setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

or change it to:

    [requestOnlineStart setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
Tom Pace
  • 2,347
  • 1
  • 24
  • 32
  • trying with application/notjson was the game changer... I taught header was the mistake. Thanks a lot – Leo Joseph Apr 28 '14 at 11:09
  • @LeoJoseph cool, I am glad I could help. Would you mind elaborating on what your actual fix was, to resolve your issue? :) – Tom Pace Apr 28 '14 at 20:16
1

Let's try (see my comment):

// replace strBodyOnlineStart NSDictionary
// NSString * strBodyOnlineStart = [NSString stringWithFormat:@"&email=***@***.com&deviceCode=*****&password_value=***"];
NSDictionary *requestObj = @{
                             @"email":  your email,
                             @"passwordValue": your password,
                             };

// Can you try jsonRequest with NSJSONSerialization framework (iOS framework default).
NSData *jsonRequest = [NSJSONSerialization dataWithJSONObject:strBodyOnlineStart options:0 error:&error];

// your url has "/" value at the end or not???
NSString *url = @"http://local.server/xxxxx/";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonRequest];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

//try set value like this
[request setValue:[NSString stringWithFormat:@"%d", [jsonRequest length]] forHTTPHeaderField:@"Content-Length"];

// Hope this format helps you. 
nmh
  • 2,497
  • 1
  • 15
  • 27
  • I am getting a sigabrt after NSData *jsonRequest = ... May be because till that line I dint get any JSON response to be parsed. – Leo Joseph Apr 26 '14 at 12:59