10

I have a problem with sending a JSON to a Server with REST API. This is the code i use:

NSString *jsonPostBody = [NSString stringWithFormat:@"'json' = '{\"user\":{\"username\":"
                          "\"%@\""
                          ",\"password\":"
                          "\"%@\""
                          "}}'",
                          [username stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                          [password stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];       
NSData *postData = [jsonPostBody dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *apiPathParams = [NSString stringWithFormat:@"%@",
                           @"getUser"
                           ];

NSURL *url = [NSURL URLWithString:[[apiPath retain] stringByAppendingString:apiPathParams]];    
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url
                                                       cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                   timeoutInterval:180.0];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:postData];
NSString* postDataLengthString = [[NSString alloc] initWithFormat:@"%d", [postData length]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:postDataLengthString forHTTPHeaderField:@"Content-Length"];
[self internalRequest:request];

This is what the API would look like, if it was a html form:

<form method="post" action="someAPI-URL">
<input name="json" value="{"user":...}" />
</form>

This is what my POST Data looks like when i add it to the request:

json={"user":{"username":"someUser","password":"somePassword"}}

For a reason I don't know the POST Data does not arrive at the server. Have i done something wrong with the formatting of the dataString? How exactly must i format my dataString so that it matches the String a form as shown above would deliver to the server?

Any help would be highly appreciated.

P.S. I would rather not use ASIHttpRequest, since i took over the project from somebody else an every other request works fine, except this post-request. So changing this whole bulk to an other connection framework would be very time consuming.

Here is the internalRequest Method's sourcecode

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
NSMutableDictionary *di = [NSMutableDictionary dictionaryWithObject:[[NSMutableData alloc] init] forKey:@"receivedData"];   
[di setObject:[NSString stringWithFormat:@"%i",identifier] forKey:@"identifier"];
if (delegate == nil) 
{ 
    delegate = self;         
}
[di setObject:delegate forKey:@"delegate"];

CFDictionaryAddValue(connectionToInfoMapping, connection, di)
Maverick1st
  • 3,774
  • 2
  • 34
  • 50
  • Can you show us your internalRequest method ? – 0x8badf00d Sep 13 '11 at 15:38
  • sure. Sorry. Forgot about that. :) But that should not be the problem. I can reach the server. I am also using the correct method (getUser) and i get a response from the server and from the right method (getUser), but my postdata won't reach the server for some reason. – Maverick1st Sep 13 '11 at 15:40
  • NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self]; this looks little scary to me. If connection has to be local variable can you change it to [NSURLConnection connectionWithRequest:req delegate:self]; can you place breakpoint in NSURLConnection delegate method - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { int statusCodeInt = [((NSHTTPURLResponse *)response) statusCode]; NSLog(@"Response is %d",statusCodeInt);} and see what the response code from your server is. – 0x8badf00d Sep 13 '11 at 15:49
  • print the post body with nslog and try calling the web service from a browser using the same string, just to make sure that web service is working fine.. – Swapnil Luktuke Sep 13 '11 at 15:50
  • @0x8badf00d I already log the output of the Server. I always get the message that username or password is wrong. After talking to the developer of the API on the server he told me, that a request is reaching the server, but this request contains no post data as it seems. The post data is leaving my simulater though, as i tested this with wireshark. So i am pretty sure it has to do something with my post data representation. But I'm not sure what it is. May be i'm only missing a Quotationmark or something. ;) – Maverick1st Sep 13 '11 at 15:56
  • @lukya I know that the webservice is fine. I tested it with an other application using the same webservice. Unfortunately i don't have the sourcecode of that other application. Typing it into the browser would be of no use, since i want to send a POST and not a GET request. – Maverick1st Sep 13 '11 at 16:00
  • i'm not talking about testing whether the web services are working fine on their own but whether they respond to your JSON data as expected.. so print your JSON string in NSLog and test using that string from a client... creating a client for testing those web services shouldn't be much of a hassle... – Swapnil Luktuke Sep 14 '11 at 06:03
  • I found the answer in [this very similar SO question](http://stackoverflow.com/questions/4456966/how-to-send-json-data-in-the-http-request-using-nsurlrequest "this very similar SO question") – Olie Oct 27 '11 at 04:04

4 Answers4

18

since you try to submit a HTTP POST header like

json={"user":{"username":"%@","password":"%@"}},

this example is fully qualified to end up in confusion.

It's a mixture of application/x-www-form-urlencoded for the whole body and application/json for the value.

Maybe a way to resolve this:

You'll probably need to adjust that HTTP header:

 [request setValue:@"application/x-www-form-urlencoded" 
forHTTPHeaderField:@"Content-Type"];

due to an encoding of the JSON part (value) of the HTTP body:

[request setHTTPBody:[[jsonPostBody stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]
                      dataUsingEncoding:NSUTF8StringEncoding 
                   allowLossyConversion:YES]];    

where stringByAddingPercentEscapesUsingEncoding is objective c jabberwocky for the PHP equivalent urlencode.

HTH

klaus
  • 1,806
  • 17
  • 20
  • You are my hero of the day. Works like a charm. No i only have to mess up the guy who gave me the interface description... :) – Maverick1st Nov 02 '11 at 13:56
0

You can test different headers and form parameters using the Chrome Advanced Rest Client. So, before coding you could know how the web service is behaving using this tool.

zeeawan
  • 6,667
  • 2
  • 50
  • 56
0

I think you have to use a JSON framework and convert jsonPostBody to it's JSON representation before sending it. Check this accepted answer , it shows how to build the request.

Community
  • 1
  • 1
Youssef
  • 3,582
  • 1
  • 21
  • 28
  • Well, since JSON is nothing more than a special String Representation of a certain context which can be transformed to Dictionarys and Arrays very easily I don't think this will make a difference. Especially since i used POST Requests earlier without a JSON framework. But I'll give it a try. May be it works :) – Maverick1st Sep 13 '11 at 15:47
0

Does this web service has a web client that you can use your browser and test. I reccomend you that if they have a web client already try using Mozilla Firefox with the plug-in firebug and check what data and headers are being sent to server with a request also it is possible to see the json string in post data tab.

After you make sure what sort of message the server expect then you can create the exact same message by yourself and send it.

For what reason you try to create your own json I dont know, but I reccomend you to use a third party library such as JSON Framework. Also I reccomend you to use ASIHttpRequest library for http requests. It makes everything eaasy.

But first thing is first, you need to be sure the type of the message, what are the parameters, headers, type and data...

Omer Faruk KURT
  • 101
  • 1
  • 6