POST with URL parameters and JSON body in AFNetwor

2019-02-13 15:00发布

问题:

I'd like to make a POST call that has both URL parameters and a JSON body:

URL http://example.com/register?apikey=mykey
JSON { "field" : "value"}

How can I use two different serializers at the same time with AFNNetworking? Here's my code with the URL parameters missing:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:@"http://example.com/register" parameters:json success:^(AFHTTPRequestOperation *operation, id   responseObject) {

回答1:

I make a post method

/**
 *  Services gateway
 *  Method  get response from server
 *  @parameter              -> object: request josn object ,apiName: api endpoint
 *  @returm                 -> void
 *  @compilationHandler     -> success: status of api, response: respose from server, error: error handling
 */
+ (void)getDataWithObject:(NSDictionary *)object onAPI:(NSString *)apiName withController:(UIViewController*)controller
                         :(void(^)(BOOL success,id response,NSError *error))compilationHandler {


    controller = controller;
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    // set request type to json
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];


    // post request to server
    [manager POST:apiName parameters:object success:^(AFHTTPRequestOperation *operation, id responseObject) {

        // NSError *error;
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject
                                                           options:0
                                                             error:&error];

        //NSString *JSONString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
        //// 

        // check the status of API
        NSDictionary *dict = responseObject;
        NSString *statusOfApi = [[NSString alloc]initWithFormat:@"%@"
                                 ,[dict objectForKey:@"OK"]];

        // IF Status is OK -> 1 so complete the handler
        if ([statusOfApi isEqualToString:@"1"] ) {

            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
            compilationHandler(TRUE,responseObject,nil);

        } else {

            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

            NSArray *errorMessages = [responseObject objectForKey:@"messages"];
            NSString *message = [errorMessages objectAtIndex:0];

            [Utilities showAlertViewWithTitle:apiName message:message];

            compilationHandler(FALSE,responseObject,nil);
        }

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSString *message = [NSString stringWithFormat:@"%@",[error localizedDescription]];
        NSLog(@"Message is %@", message);

        NSString *errorMessage = [NSString stringWithFormat:@"%@",[error localizedDescription]];
        if (!([message rangeOfString:@"The request timed out."].location == NSNotFound)) {
            [Utilities showAlertViewWithTitle:apiName message:errorMessage];
        }

        compilationHandler(FALSE,errorMessage,nil);
    }];

    // For internet reachibility check if changes its state
    [self checkInternetReachibility:manager];
}

**for Example when we call the Service **

  // calling service gateway API
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                 "field",@"value",
                                 nil];
        [self getDataWithObject:dict onAPI:KGet_Preferences  withController:(UIViewController*)controller :^(BOOL success, id response, NSError *error) {

            if( success ) {
                NSMutableDictionary *data = [[response valueForKey:@"data"] valueForKey:@"preferences"];
                compilationHandler(success,data,error);
            } else {
                compilationHandler(success,nil,error);
            }
        }];


回答2:

I believe there is no automatic way of doing it. However, there is a simple way of achieving it manually:

- (NSMutableURLRequest *)someRequestWithBaseURL:(NSString *)baseUrl
                                          method:(NSString *)method
                                            path:(NSString *)path
                                      uriParameters:(NSDictionary *)uriParameters
                                  bodyParameters:(NSDictionary *)bodyParameters

NSURL *url = [NSURL URLWithString:path relativeToURL:[NSURL URLWithString:baseUrl]];

AFHTTPRequestSerializer *httpRequestSerializer = [AFJSONRequestSerializer serializerWithWritingOptions:0]

NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:bodyParameters];

if ([httpRequestSerializer.HTTPMethodsEncodingParametersInURI containsObject:method]) {
    [parameters addEntriesFromDictionary:uriParameters];
} else {
    NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
    // For urlEncodedString, check http://stackoverflow.com/a/718480/856549
    urlComponents.percentEncodedQuery = [uriParameters urlEncodedString];
    url = [urlComponents URL];
}

NSError *error;
NSURLRequest *request = [httpRequestSerializer requestWithMethod:method
                                                       URLString:[url absoluteString]
                                                      parameters:parameters
                                                           error:&error];