Kex
Kex

Reputation: 8599

Using NSURLSession to POST, what is the correct way to post the variables?

I am following this tutorial: http://www.raywenderlich.com/2965/how-to-write-an-ios-app-that-uses-a-web-service. Trying to set up a basic web service. Seems like the tutorial is old material and ASIHTTPRequest is no longer continued. I have been trying to use NSURLRequest instead. First question, is NSURLRequest a pretty standard way to be doing this? I just want something for basic GET, POST etc, should I be doing it a different way?

My code is:

-(BOOL)textFieldShouldReturn:(UITextField *)textField{

    NSLog(@"We want to unlock for the code %@",self.textField.text);

    //Get a device ID, (actually can't do this aymore)
    NSString *uniqueIdentifier = @"My iPhone";
    NSString *code = self.textField.text;


    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.madasd.co/promos/"]];

    request.HTTPMethod=@"POST";

    //Set the header fields
    [request setValue:@"application/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

    NSString *myString = [NSString stringWithFormat:@"rw_app_id=1&code=%@&device_id=%@",code,uniqueIdentifier];
    NSLog(@"%@",myString);
    NSData *requestBodyData = [myString dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody=requestBodyData;

    //Create url and fire request

    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];

    [conn start];


    return TRUE;
}



- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{


    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",string);

}

Second question, I have tested the backend using curl so I know it works fine, however the response I get is "Invalid Request", I think this is because the string I am sending is not correct. Am I doing this correct using the var names and & operators? Any pointers on this would be great! thanks. (Running a LAMP server on Linode!)

EDIT:

Also tried sending as JSON:

[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSDictionary *mapData = [[NSDictionary alloc]initWithObjectsAndKeys:@"1",@"rw_app_id",code,@"code",uniqueIdentifier,@"device_id", nil];
NSError *error = nil;
NSData *requestBodyData = [NSJSONSerialization dataWithJSONObject:mapData options:0 error:&error];
request.HTTPBody=requestBodyData;

Still getting the same error.

Upvotes: 1

Views: 740

Answers (2)

Rob
Rob

Reputation: 437582

A couple of thoughts:

  1. Don't use NSURLConnection. It is deprecated as of iOS 9. Use NSURLSession. See Using NSURLSession in the URL Loading System Programming Guide.

  2. Decide what type of request you need to prepare. You specified application/xml in your header, but are creating a application/x-www-form-urlencoded request. Your Content-Type header must match how you're building the HTTPBody.

    What type of request does your server require? x-www-form-urlencoded? XML? JSON?

    Also, what type of response does your server provide?

  3. If building a application/x-www-form-urlencoded request (as suggested by the body of your request), you are not properly percent escaping the values (see https://stackoverflow.com/a/20398755/1271826).

  4. If you use delegate based NSURLConnection or NSURLSession, you should not just grab the results in didReceiveData. What you need to do is

    • Instantiate a NSMutableData before starting the request;

    • Have didReceiveData merely append to that NSMutableData;

    • Only when connectionDidFinishLoading: (in NSURLConnection) or URLSession:task:didCompleteWithError: (in NSURLSession) is called, should you then use the NSMutableData.

    Alternatively, if using the block-based NSURLSession, this concern is completely eliminated (since you're not implementing any delegate methods). Using completionHandler-based methods of NSURLSession is much easier.

  5. If all of this is too complicated, you might consider using AFNetworking's AFHTTPSessionManager (but not AFHTTPRequestOperationManager) to build your requests. It gets you out of the weeds of properly building requests, implementing delegate methods, etc.

Upvotes: 2

Cocoadelica
Cocoadelica

Reputation: 3026

You might need to wrap the strings into a dictionary and get the NSData object from a call to NSJSONSerialization. Though it depends on the form expected by the server.

Upvotes: 0

Related Questions