Following code is to submit images through an operationQueue. The requests are all fired one by one correctly, the server response contains the image file name which client needs to get hold of. The problem is that the reponseObject for the success/failure block is not expected parsed JSON but type of NSInLineData shown in debugger. Now I suspect the code to construct the operation from the NSMutableURLRequest caused the issue. Please help.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSMutableURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:#"POST"
URLString:podURLString parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSError *error;
BOOL success =[formData appendPartWithFileURL:imgURL name:#"images" fileName:img.path
mimeType:#"image/jpg" error:nil];
if (!success)
NSLog(#"appendPartWithFileURL error: %#", error);} error:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Image Success: %#", [responseObject description]);
NSString *imagePath = [response objectForKey:#"imageFileName"];
[self.delegate networkManager:self didSubmitDeliveryImageForImageID:imagePath];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Image Error: %#", error);
NSLog(#"image error: %#", [operation.responseObject description]);
NSString *imageFilePath = [operation.responseObject objectForKey:#"imageFileName"];
[self.delegate networkManager:self didFailSubmitDeliveryImageForImageID:imageFilePath];
}];
[manager.operationQueue addOperation:operation];
When you get the response as NSInLineData. It's good to go now. You can write below single line of code to get NSDictionary if it supports json format.
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseObjec options:0 error:nil];
Just add this line of code before your AFHTTPRequestOperation block
**operation.responseSerializer = [AFJSONResponseSerializer serializer];**
i want to implement afnetworking with put request, but it always shows error when i run it.
it works fine with post method, but when i change it to PUT it shows error.
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:urls];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"345", #"page_id",
#"john",#"username",
nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"PUT"
path:#""
parameters:params];
//Add your request object to an AFHTTPRequestOperation
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation,
id responseObject) {
NSString *response = [operation responseString];
NSLog(#"response: [%#]",response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", [operation error]);
}];
//call start on your request operation
[operation start];
the error says:
Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 404" UserInfo=0x75a9d40 {NSLocalizedRecoverySuggestion={"status":false,"error":"Unknown method."}
I've been trying to get a grip on AFHTTPClient in the specific instance of dispatching a request to a REST-based service that requires OAuth authentication. I have no problem with creating the OAuth authentication using GTMOAuth.
I can also successfully marshall parameters to dispatch the request and obtain a well-formed JSON response using a hand-cobbled NSMutableURLRequest and both AFJSONRequestOperation and an NSURLConnection. Those latter two mechanics were my sanity check that I was touching the service correctly.
I get a response using
[AFHTTPClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject)]
but no matter what — it's interpreted as text/plain. The returned object's class is __NCFData.
No bueno.
This bit of code doesn't want to return a response that's a dictionary of any sort.
- (IBAction) testFlickr {
// marshall parameters
NSString *urlStr = #"http://api.flickr.com/";
NSURL *url = [NSURL URLWithString:urlStr];
AFHTTPClient *client = [[AFHTTPClient alloc]initWithBaseURL:url];
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];
[client setParameterEncoding:AFJSONParameterEncoding];
NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:#"json", #"format", #"66854529#N00", #"user_id", #"1", #"jsoncallback", nil];
NSString *path = [[NSString alloc]initWithFormat:#"services/rest/?method=flickr.people.getPhotos"];
NSMutableURLRequest *af_request = [client requestWithMethod:#"GET" path:path parameters:params];
// flickrAuth instance variable is an instance of GTMOAuthAuthentication
[self.flickrAuth authorizeRequest:af_request];
[client setAuthorizationHeaderWithToken:[self.flickrAuth accessToken]];
[client setDefaultHeader:#"Accept" value:#"application/json"];
[client requestWithMethod:#"GET" path:path parameters:params];
LOG_FLICKR_VERBOSE(0, #"Can Authorize? %#", ([self.flickrAuth canAuthorize] ? #"YES":#"NO"));
LOG_FLICKR_VERBOSE(0, #"%#", client);
// first way of trying..
AFHTTPRequestOperation *af_operation = [client HTTPRequestOperationWithRequest:af_request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *str = [[NSString alloc] initWithData:responseObject
encoding:NSUTF8StringEncoding];
LOG_FLICKR_VERBOSE(0, #"Weird af_operation semantics, but.. %#", str);
LOG_FLICKR_VERBOSE(0, #"Weird af_operation semantics returns %#", [responseObject class]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//
LOG_FLICKR_VERBOSE(0, #"Weird af_operation semantics, error.. %#", error);
}];
[af_operation start];
}
This request goes through okay. The response data itself is what I'd expect, but it is not any kind of dictionary class.
I'd rather keep to using methods of AFHTTPClient (as opposed to, for example, [AFJSONRequestOperation JSONRequestOperationWithRequest]) so I can use AFHTTPClient's Reachability methods and so forth.
Strangely (to me, at least) if I do the request like this:
NSMutableURLRequest *aj_request = [client requestWithMethod:#"GET" path:path parameters:params];
[self.flickrAuth authorizeRequest:aj_request];
AFJSONRequestOperation *aj_operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:af_request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONRequestOperation %#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONREquestOperation Error %#", error);
}];
[aj_operation start];
It fails with a "401" because it was expecting application/json in the response header and instead thinks it's received text/plain
But, if I do the request like this:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[[NSURL alloc]initWithString:#"http://api.flickr.com/services/rest/?method=flickr.people.getPhotos&format=json&user_id=66854529#N00&nojsoncallback=1"]];
[self.flickrAuth authorizeRequest:request];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
LOG_FLICKR_VERBOSE(0, #"Success Flickr =========\n%# %#", JSON, [JSON valueForKeyPath:#"photos.total"]);
/////handler(JSON, nil);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
LOG_FLICKR(0, #"URL Was %#", url);
LOG_FLICKR(0, #"Failed Flickr ==========\n%# %#", error, JSON);
/////handler(nil, error);
}];
[operation start];
It works fine, including nice JSON, dictionary-formed data.
In the first instance, I'm using AFHTTPClient to produce the NSMutableURLRequest. In the second instance, I'm creating the NSMutableURLRequest on my own. In both cases I'm using AFJSONRequestOperation to dispatch the request leaving the only culprit for the problem to (besides myself..) AFHTTPClient.
In the first example that I can get to work, it's not returning JSON-y data.
In the second example AFHTTPClient seems to create an NSMutableURLRequest that blatantly fails — but (AFAICT) the same URL succeeds when that URL is created "by hand" using [NSMutableURLRequest requestWithURL].
I wonder — what am I missing when using AFHTTPClient?
Help?
In your first code example, it looks like you're doing NSMutableURLRequest *af_request = [client requestWithMethod:#"GET" path:path parameters:params]; and then setting default headers afterwards. Default headers only get applied to requests created after they were specified. Maybe that's where things are going amiss.
Also, that 401 error may be complaining about its content type, but 401 is an error status code, meaning that you're unauthenticated.
I ended up removing all the header parameters to isolate the problem, but it made no difference. Examining the response quite closely gave me a clue. While Flickr does return "JSON" it is not Lint-free, it seems and requires a tweak to one of the parameters. I had been sending jsoncallback=1 but it should be nojsoncallback=1. Once I fixed that parameter AFJSONRequestOperation handles the response correctly and parses the JSON.
My final code looks like this (for others, n.b. the nojsoncallback=1 parameter)
- (IBAction)testFlickrAFJSON:(id)sender
{
// marshall parameters
NSString *urlStr = #"http://api.flickr.com/";
NSURL *url = [NSURL URLWithString:urlStr];
//NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:#"json", #"format", #"66854529#N00", #"user_id", nil];
NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:#"json", #"format", #"66854529#N00", #"user_id", #"1", #"nojsoncallback", nil];
NSString *path = [[NSString alloc]initWithFormat:#"services/rest/?method=flickr.people.getPhotos"];
AFHTTPClient *client = [[AFHTTPClient alloc]initWithBaseURL:url];
NSMutableURLRequest *af_request = [client requestWithMethod:#"GET" path:path parameters:params];
[self.flickrAuth authorizeRequest:af_request];
LOG_FLICKR_VERBOSE(0, #"Can Authorize? %#", ([self.flickrAuth canAuthorize] ? #"YES":#"NO"));
AFJSONRequestOperation *af_operation_2 = [AFJSONRequestOperation JSONRequestOperationWithRequest:af_request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONRequestOperation Alt %#", JSON);
LOG_FLICKR_VERBOSE(0,#"AFJSONRequestOperation Alt response MIMEType %#",[response MIMEType]);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONREquestOperation Alt Error %#", error);
NSHTTPURLResponse *resp = [[error userInfo] valueForKey:AFNetworkingOperationFailingURLResponseErrorKey];
LOG_FLICKR_VERBOSE(0,#"AFJSONRequestOperation Alt Error response MIMEType %#",[resp MIMEType]);
}];
[af_operation_2 start];
}
When i request data from server with AFHHTPClient this way:
[[NetworkHelper sharedHelper] postPath:path parameters:parameters] success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", [operation class]);
NSLog(#"%#", [responseObject class]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", [error localizedDescription]);
}];
I got this:
2012-10-10 13:24:36.881 MyApp[4635:c07] AFHTTPRequestOperation
2012-10-10 13:24:36.881 MyApp[4635:c07] NSConcreteData
I tried to force application/json content-type in server's response, but i still got AFHTTPRequestOperation.
But if i use this:
[[AFJSONRequestOperation JSONRequestOperationWithRequest:[NSURLRequest requestWithURL:myURL] success:^(NSURLRequest *request, NSURLResponse *response, id JSON) {
NSLog(#"%#", JSON);
} failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#", [error localizedDescription]);
}] start];
I got JSON responce i need.
What should i do to get JSON response with AFHTTPClient?
UPDATE:
I add NSLog(#"%#",[self.response MIMEType]); in - (BOOL)hasAcceptableContentType method in AFHTTPRequestOperation class and i recieve
2012-10-11 09:48:25.052 MyApp[3339:3803] application/json
but i still get AFHTTPRequestOperation class.
Try to set AFHTTPRequestOperation:acceptableContentTypes:
+ (NSSet *)acceptableContentTypes {
return [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", nil];
}
I've had the same problem that I suspect may have something to do with the way AFJSONRequestOperation handles responses.
I've dispatched the exact same request using AFJSONRequestOperation using the NSMutableURLRequest returned from [AFHTTPClient clientRequestWithMethod] and constructing my own NSMutableURLRequest and each has a response with a different mime type — the one from [AFHTTPClient clientRequestWithMethod] indicates text/plain; the one from NSMutableURLRequest constructed "by hand" is text/json.
I've mentioned this here in this question:
AFNetworking with AFHTTPClient with AFJSONRequestOperation // MIME-Type Issues
I am using AFHTTPRequestOperation to get a couple of HTML pages to parse.
The problem i'm having, is if I use a wrong port number for example, when connecting to the server, the 'failed' error block doesn't fire. Instead the completion block fires but the responce string is nil.
I'm just switching over to AFNetworking from ASIHTTP, and with ASIHTTP this would produce an error.
Surely this should provide an error? How can I trap this?
NSString *urlString;
urlString = [NSString stringWithFormat:#"%#://%#:%#/",kHttp,_IP,_Port];
NSURL *url = [NSURL URLWithString:urlString];
// Set authorization
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient setAuthorizationHeaderWithUsername:_User password:_Pass];
NSURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"Info.htm" parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([self parseInfoLive:operation.responseString])
_count_parsed++;
if (_count_parsed == 2)
[[NSNotificationCenter defaultCenter] postNotificationName:#"downloadsComplete" object:nil];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error during connection: %#",error.description);
[[NSNotificationCenter defaultCenter] postNotificationName:#"errorConnecting" object:nil];
}];
[operation start];
This seems to be a bug in AFNetworking, even 2.5 years after this question. This occurs when response contains a special character(it can appear as a space since sometimes even text viewers too can't parse it). You can try converting recieved JSON string to NSUTF8StringEncoding and then use it as NSData, if needed.
NSURL *url = <YOUR REQUEST URL>
NSString *data = [NSString stringWithContentsOfURL:url];
NSData *metOfficeData = [data dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = [NSError new];
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:metOfficeData options:kNilOptions error:&error];