How to make POST NSURLRequest with 2 parameters?

19,997

Solution 1

It will probably be easier to do if you use AFNetworking. If you have some desire to do it yourself, you can use NSURLSession, but you have to write more code.

  1. If you use AFNetworking, it takes care of all of this gory details of serializing the request, differentiating between success and errors, etc.:

    NSDictionary *params = @{@"firstname": @"John", @"lastname": @"Doe"};
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager POST:urlString parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"responseObject = %@", responseObject);
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"error = %@", error);
    }];
    

    This assumes that the response from the server is JSON. If not (e.g. if plain text or HTML), you might precede the POST with:

    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
  2. If doing it yourself with NSURLSession, you might construct the request like so:

    NSDictionary *params = @{@"firstname": @"John", @"lastname": @"Doe"};
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[self httpBodyForParameters:params]];
    

    You now can initiate the request with NSURLSession. For example, you might do:

    NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"dataTaskWithRequest error: %@", error);
        }
    
        if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
            NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
            if (statusCode != 200) {
                NSLog(@"Expected responseCode == 200; received %ld", (long)statusCode);
            }
        }
    
        // If response was JSON (hopefully you designed web service that returns JSON!),
        // you might parse it like so:
        //
        // NSError *parseError;
        // id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
        // if (!responseObject) {
        //     NSLog(@"JSON parse error: %@", parseError);
        // } else {
        //     NSLog(@"responseObject = %@", responseObject);
        // }
    
        // if response was text/html, you might convert it to a string like so:
        //
        // NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        // NSLog(@"responseString = %@", responseString);
    }];
    [task resume];
    

    Where

    /** Build the body of a `application/x-www-form-urlencoded` request from a dictionary of keys and string values
    
     @param parameters The dictionary of parameters.
     @return The `application/x-www-form-urlencoded` body of the form `key1=value1&key2=value2`
     */
    - (NSData *)httpBodyForParameters:(NSDictionary *)parameters {
        NSMutableArray *parameterArray = [NSMutableArray array];
    
        [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
            NSString *param = [NSString stringWithFormat:@"%@=%@", [self percentEscapeString:key], [self percentEscapeString:obj]];
            [parameterArray addObject:param];
        }];
    
        NSString *string = [parameterArray componentsJoinedByString:@"&"];
    
        return [string dataUsingEncoding:NSUTF8StringEncoding];
    }
    

    and

    /** Percent escapes values to be added to a URL query as specified in RFC 3986.
    
     See http://www.ietf.org/rfc/rfc3986.txt
    
     @param string The string to be escaped.
     @return The escaped string.
     */
    - (NSString *)percentEscapeString:(NSString *)string {
        NSCharacterSet *allowed = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"];
        return [string stringByAddingPercentEncodingWithAllowedCharacters:allowed];
    }
    

Solution 2

NSDictionary *params = @{@"firstname": @"John", @"lastname": @"Doe"};
NSMutableString *str = [NSMutableString stringWithString:@"http://yoururl.com/postname?"];
NSArray *keys = [params allKeys];
NSInteger counter = 0;
for (NSString *key in keys) {
    [str appendString:key];
    [str appendString:@"="];
    [str appendString:params[key]];
    if (++counter < keys.count) { // more params to come...
        [str appendString:@"&"];
    }
}
NSURL *url = [NSURL URLWithString:str];
// should give you: http://yoururl.com/postname?firstname=John&lastname=Doe
// not tested, though
Share:
19,997
l.vasilev
Author by

l.vasilev

Product developer.

Updated on June 05, 2022

Comments

  • l.vasilev
    l.vasilev almost 2 years

    I want to add 2 parameters to NSURLRequest. Is there a way or should I use AFnetworking?

  • CouchDeveloper
    CouchDeveloper over 9 years
    URLWithStringrequires a properly encoded URL. Your approach does not encode the URL components at all. So, it will fail eventually.
  • l.vasilev
    l.vasilev over 9 years
    yes i am receiving JSON .this is great and complete answer.THAKS man! :) Can i ask you just one thing for AFNetworking. this is my code :[manager POST:@"tourneys/portal.php" parameters:@{ @"cmd":@"get_games", @"uid_first":@"1" } success:^(NSURLSessionDataTask task, id responseObject) { NSDictionary response = (NSDictionary* )responseObject; I am receiving json from my server. Is this cast to NSDictionary valid .I saw it's working but i can't figure it out why.I am not using explicit any serialiser. Thanks in advance.
  • Rob
    Rob over 9 years
    Since you haven't specified a responseSerializer, that means you're using the default AFJSONResponseSerializer. So, it's doing the JSON conversion for you.
  • AppsolutEinfach
    AppsolutEinfach almost 8 years
    For iOS 9 replace CFURLCreateStringByAddingPercentEscapes() by stringByAddingPercentEncodingWithAllowedCharacters:[NSCharac‌​terSet URLQueryAllowedCharacterSet] in percentEscapeString:.
  • Rob
    Rob almost 8 years
    @AppsolutEinfach - No, because that character set will let & and + pass unescaped (because they're allowed in query URL; but if these delimiters occur within value within query, you have to escape them). See part 2 of stackoverflow.com/a/35912606/1271826 if you want to see how you have to modify URLQueryAllowedCharacterSet properly.
  • AppsolutEinfach
    AppsolutEinfach almost 8 years
    @Rob - You're totally right. Thanks for your correction.
  • Nat
    Nat over 5 years
    I would argue that attaching libraries is the best way of doing everything. AFNetworking is not required at this point. No need to attach extra dependency.
  • Rob
    Rob over 5 years
    To each his own. That’s why I outlined both approaches above.
  • Doon
    Doon over 4 years
    It won't "fail eventually". It will fail if some special char is in the parameter