Search code examples
iospostasihttprequestnsmutableurlrequest

ASIHTTP post works different than NSMutableURLRequest


i used to have a method to post:

-(void) execMethod:(NSString*)methodName andParams:(NSArray*)parameters withID:(NSString*)identificator {

//RPC
NSMutableDictionary* reqDict = [NSMutableDictionary dictionary];
[reqDict setObject:methodName forKey:@"method"];
[reqDict setObject:parameters forKey:@"params"];
[reqDict setObject:identificator forKey:@"id"];

//RPC JSON
NSString* reqString = [NSString stringWithString:[reqDict JSONRepresentation]];
NSData* requestData = [NSData dataWithBytes:[reqString UTF8String] length:[reqString length]];

//Request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];


//prepare http body
[request setHTTPMethod: @"POST"];
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody: requestData];


if (urlConnection != nil) {
    [urlConnection release];
    urlConnection = nil;
}

urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
[request release];

    }

Now I want to use ASIHttp and I wrote that function:

-(void)startRequest:(NSString*)methodName andParams:(NSArray*)parameters withID:(NSString*)identificator
   {

    NSMutableDictionary* reqDict = [NSMutableDictionary dictionary];
[reqDict setObject:methodName forKey:@"method"];
[reqDict setObject:parameters forKey:@"params"];
[reqDict setObject:identificator forKey:@"id"];

//RPC JSON
NSString* reqString = [NSString stringWithString:[reqDict JSONRepresentation]];

//Request
    NSData* requestData = [NSData dataWithBytes:[reqString UTF8String] length:[reqString length]];



asiRequest=[ASIFormDataRequest requestWithURL:url];

[asiRequest addRequestHeader:@"Accept" value:@"application/json"];
[asiRequest addRequestHeader:@"Content-Length" value:[NSString stringWithFormat:@"%d", [requestData length]]];
[asiRequest addRequestHeader:@"Content-Type" value:@"application/x-www-form-urlencoded"];

[asiRequest appendPostData:requestData];
[asiRequest setDelegate:self];

[asiRequest startAsynchronous];

}

But it doesn't behave same.It should return me a json. First one works correctly but second doesn't. Where is my fault?

Thanks


Solution

  • From your code sample it looks like you are submitting content of type "application/json", but you are setting the Content-Type to be "application/x-www-form-urlencoded".

    ASIHTTP has special handling for "application/x-www-form-urlencoded". I think you may be running into a problem with that special handling.


    After looking at ASI's website

    I found the following:

    PUT requests and custom POSTs

    If you want to send data via PUT, or want to send it with POST but prefer to create the POST body yourself, use appendPostData: or appendPostDataFromFile:.

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request appendPostData:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]];
    // Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody:
    [request setRequestMethod:@"PUT"];
    

    So by using ASIHTTPRequest instead of ASIFormDataRequest you will avoid the special handling. So you should be able to do the following (NOTE: Setting the content length should not be needed):

    asiRequest = [ASIHTTPRequest requestWithURL:url];
    
    [asiRequest addRequestHeader:@"Accept" value:@"application/json"];
    [asiRequest addRequestHeader:@"Content-Type" value:@"application/x-www-form-urlencoded"];
    
    [asiRequest setPostBody:requestData];
    [asiRequest setDelegate:self];
    
    [asiRequest startAsynchronous];