How to set HTTP request body using AFNetwork's AFHTTPRequestOperationManager?

I am using AFHTTPRequestOperationManager (2.0 AFNetworking library) for a REST POST request. But the manager only have the call to set the parameters.

-((AFHTTPRequestOperation *)POST:(NSString *)URLString
                  parameters:(NSDictionary *)parameters
                     success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                     failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

I need to set HTTP request body with a string as well. How can I do it using the AFHTTPRequestOperationManager? Thanks.

  • Objective-C: NSString not being entirely decoded from UTF-8
  • Why does Safari Mobile have trouble handling many input fields on iOS 8
  • Install Realm in a Swift App
  • ld: library not found for -lz.1.2.3
  • Can you develop native iPhone apps in Ruby?
  • how to download files from url and store in document folder
  • 7 Solutions Collect From Internet About “How to set HTTP request body using AFNetwork's AFHTTPRequestOperationManager?”

    I had the same problem and solved it by adding code as shown below:

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL
                  cachePolicy:NSURLRequestReloadIgnoringCacheData  timeoutInterval:10];
    
    [request setHTTPMethod:@"POST"];
    [request setValue:@"Basic: someValue" forHTTPHeaderField:@"Authorization"];
    [request setValue: @"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody: [body dataUsingEncoding:NSUTF8StringEncoding]];
    
    AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    op.responseSerializer = [AFJSONResponseSerializer serializer];
    [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    
        NSLog(@"JSON responseObject: %@ ",responseObject);
    
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", [error localizedDescription]);
    
    }];
    [op start];
    

    for AFHTTPRequestOperationManager

    [requestOperationManager.requestSerializer setValue:@"your Content Type" forHTTPHeaderField:@"Content-Type"];
    [requestOperationManager.requestSerializer setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"];
    
    // Fill parameters
    NSDictionary *parameters = @{@"name"        : @"John",
                                 @"lastName"    : @"McClane"};
    
    // Customizing serialization. Be careful, not work without parametersDictionary
    [requestOperationManager.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
    
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
        NSString *argString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        return argString;
    }];
    
    [requestOperationManager POST:urlString parameters:parameters timeoutInterval:kRequestTimeoutInterval success:^(AFHTTPRequestOperation *operation, id responseObject) {
    
        if (success)
            success(responseObject);
    
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    
        if (failure)
            failure(error);
    }];
    

    Check what that convenience method (POST:parameters:success:failure) is doing under the hood and do it yourself to get access to actual NSMutableRequest object.

    I’m using AFHTTPSessionManager instead of AFHTTPRequestOperation but I imagine the mechanism is similar.

    This is my solution:

    1. Setup Session Manager (headers etc)

    2. Manually create NSMutable request and add my HTTPBody, basically copying-pasting code inside that convenience method. Looks like this:

      NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:<url string>] absoluteString] parameters:parameters];
      
      [request setHTTPBody:[self.POSTHttpBody dataUsingEncoding:NSUTF8StringEncoding]];
      __block NSURLSessionDataTask *task = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
          if (error) {
             // error handling
          } else {
              // success
        }
      }];
      
      [task resume];
      

    If you dig a little in sources of AFNetworking you will find that in case of POST method parameters are set into body of your HTTP request.

    Each key,value dictionary pair is added to the body in form key1=value1&key2=value2. Pairs are separated by & sign.

    Search for application/x-www-form-urlencoded in AFURLRequestSerialization.m.

    In case of a string which is only a string, not key value pair then you might try to use AFQueryStringSerializationBlock http://cocoadocs.org/docsets/AFNetworking/2.0.3/Classes/AFHTTPRequestSerializer.html#//api/name/setQueryStringSerializationWithBlock: but this is only my guess.

    You could create your own custom subclass of AFHTTPRequestSerializer, and set this as the requestSerializer for your AFHTTPRequestOperationManager.

    In this custom requestSerializer, you could override

    - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request         
                                   withParameters:(id)parameters 
                                            error:(NSError *__autoreleasing *)error;
    

    Inside your implementation of this method, you’ll have access to the NSURLRequest, so you could do something like this

    - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request     
                                   withParameters:(id)parameters 
                                            error:(NSError *__autoreleasing *)error  
    {    
        NSURLRequest *serializedRequest = [super requestBySerializingRequest:request withParameters:parameters
         error:error];
        NSMutableURLRequest *mutableRequest = [serializedRequest mutableCopy];          
        // Set the appropriate content type
        [mutableRequest setValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];              
        // 'someString' could eg be passed through and parsed out of the 'parameters' value
        NSData *httpBodyData = [someString dataUsingEncoding:NSUTF8StringEncoding];
        [mutableRequest setHTTPBody:httpBodyData];
    
        return mutableRequest;
    }
    

    You could take a look inside the implementation of AFJSONRequestSerializer for an example of setting custom HTTP body content.

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    [manager POST:url parameters:jsonObject success:^(AFHTTPRequestOperation *operation, id responseObject) {
        //success
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //fail
    }];
    

    This is the best and most concise way that I have found.

    May be we can use the NSMutableURLRequest, here is the code :

    NSURL *url = [NSURL URLWithString:yourURLString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:60.0];
    
    [request setHTTPMethod:@"POST"];
    NSData *JSONData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
    NSString *contentJSONString = [[NSString alloc] initWithData:JSONData encoding:NSUTF8StringEncoding];
    [request setHTTPBody:[contentJSONString dataUsingEncoding:NSUTF8StringEncoding]];
    
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [connection start];