I'm using AFHTTPRequestOperationManager for a POST request. Now I'm deliberately entering incorrect information to handle a 400 error code. Now, the web service actually returns a JSON with a message explaining to the user what they've done wrong. I would very much like to get this JSON to display the message in a UIAlertView. However, the failure block of:
[operationManager POST:ServerURL parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: Status Code: %d", operation.response.statusCode);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed: Status Code: %d", operation.response.statusCode);
}];
doesn't pass down a responseObject like the one in the success block. So does anyone know how I can access the JSON returned by the Web Service with the 400 error? The NSError *error simply gives me Request failed: bad request (400) and not the JSON returned.
Any help would be appreciated,Mike
Looking at the code for - responseObject, it appears that an HTTP error prevents it from being populated. You can grab the responseData directly and parse it yourself, but I would say this is either a bug or a good enhancement request. (It looks like - responseObject probably should be checking self.responseSerializationError, not self.error, when deciding if it should try to build a response object.)
You can do either of these solutions
1) Set the acceptableStatusCodes to accept your 400 statusCode, and you handle in the success block
manager.responseSerializer.acceptableStatusCodes = [NSIndexSet indexSetWithIndex:400];
2) Create a custom ResponseSerializer, like this JSONResponseSerializerWithData, to insert the responseObject into the NSError userInfo, and handle in the failure block
Pro tip: AFNetworking is opensource, just take a look at AFHTTPRequestOperation for methods
setCompletionBlockWithSuccess:failure:
responseObject
error
I also faced same problem in AFNetworking, as instead of using
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
Please try to use that one :-
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
thanks,
Following code worded for me:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:#"parse-application-id-removed" forHTTPHeaderField:#"X-Parse-Application-Id"];
[manager.requestSerializer setValue:#"parse-rest-api-key-removed" forHTTPHeaderField:#"X-Parse-REST-API-Key"];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
manager.securityPolicy.allowInvalidCertificates = YES;
NSString *URLString = [NSString stringWithFormat:#"%#/%#", BASE_URL,methodName];
[manager POST:URLString parameters:requestDict success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
[myDelegate StopIndicator];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
[myDelegate StopIndicator];
}];
Related
I am using AFNetworking V2.5.4.
The default timeout for AFN is 60s, this is too long for my app. I want to set it as 20s.
So I tried follow code manager.requestSerializer.timeoutInterval = 20;
But it's not working. I searched some post saying I need add [manager.requestSerializer willChangeValueForKey:#"timeoutInterval"];
manager.requestSerializer.timeoutInterval = 3;
[manager.requestSerializer didChangeValueForKey:#"timeoutInterval"];
Still, it's not working.
Follow is my code piece
+ (AFHTTPRequestOperation *)sendRequestWithRequest:(NSMutableURLRequest*) request
manager:(AFHTTPRequestOperationManager *)manager
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure{
[manager.requestSerializer willChangeValueForKey:#"timeoutInterval"];
manager.requestSerializer.timeoutInterval = 3;
[manager.requestSerializer didChangeValueForKey:#"timeoutInterval"];
NSLog(#"manager %#, start time %lf",manager, [[NSDate date] timeIntervalSince1970]);
AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (operation.response.statusCode) {
success(operation, responseObject);
}else{
failure(operation, nil);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(operation, error);
}];
[manager.operationQueue addOperation:operation];
return operation;}
I am using
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
to communicate with the server, and it works great.
But sometimes, there is an error on the server, and it's response is not in json format. My partner wants me to show the error string, but since it went to the failure block, I can hardly get the original response string.
Anyone can help?
You may log operation.responseString line in success and failure block both to get response string of server.
If webservice has some kind of error and provide invalid json or response then log [error description] in failure block.
For reference please check below code snippet.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setTimeoutInterval:120];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[manager POST:[[NSString stringWithFormat:#"%#",URL]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Response: %#", operation.responseString);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %# \n %#", operation.responseString,[error description]);
}];
In the failure block, add these codes:
NSDictionary *userInfo = [error userInfo];
NSString *message = [userInfo objectForKey:#"message"];
I think message is what you need, you can use NSLog to reveal the info.
To take error code(response code) you can use [operation.response statusCode];
Error detail should be here
id responseObject = error.userInfo[kErrorResponseObjectKey];
Referanced from: http://www.splinter.com.au/2014/09/10/afnetworking-error-bodies/
Some time, my server slow to response and I got this message in response, The Operation couldn't completed.(NSURLErrorDomain error -1004)
How to handle such errors?
P.S. I'm using AFNetworking for this.
You may increase the time-out by overriding the get/post methods
Following is the example for get method
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:#"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil];
[request setTimeoutInterval:ADD_YOUR_TIME_OUT_INTERVAL];
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
P.S. I used this approach in the previous version of AFNetwork, by subclassing AFHTTPClient. I didn't test it in the new version's AFHTTPRequestOperationManager.
This may be helpful : https://stackoverflow.com/a/22666837/1292441
I am developer iOS. I have a problem about AFHTTPRequestOperationManager request POST to server(JBoss) Java. When I request POST with Multipart is good response, and not problem. But, when I request POST only string to server, server show me error:
11:57:19,815 ERROR [UserRest] Problem on login email: null password:
null 11:57:19,817 ERROR [STDERR] java.lang.Exception: MISSING ARGUMENTS
This show me, send parameters null. This method:
AFHTTPRequestOperation *)POST:(NSString *)URLString parameters:(NSDictionary *)parameters success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
I don't understand, why send parameters null.. My code is:
NSString *strURL = #"http://YOUR_IP/YOUR_PATH/login";
__block const NSString *strResultResponse = #"";
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = NO;
AFJSONRequestSerializer *serializerRequest = [AFJSONRequestSerializer serializer];
[serializerRequest setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
AFJSONResponseSerializer *serializerResponse = [AFJSONResponseSerializer serializer];
serializerResponse.readingOptions = NSJSONReadingAllowFragments;
serializerResponse.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
manager.requestSerializer = serializerRequest;
manager.responseSerializer = serializerResponse;
NSDictionary *parameters = #{#"email":#"xxxxxx#xxxx.xxxx",#"password":#"xxxx"};
[manager POST:strURL parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", operation.responseString);
}];
I tried many ways, but not result. Please help me.
I am trying to make a simple request with the new AFNetworking 2.0 release and I cannot seem to get it to post. I get a response back from the server "Expecting text/json or application/json body" but according to the documentation on AFNetworking's GitHub page, I'm doing everything as I should be. It's also worth mentioning that it appears the operation.request.HTTPBody in the last line of my code always appears to be nil.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *request = #{#"email": self.email.text, #"password": self.password.text};
[manager POST:login parameters:request constructingBodyWithBlock:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"DONE!");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed to log in: %#", operation.responseString);
NSLog(#"Here's the request: %#", operation.request.HTTPBody);
}];
According to the documentation
POST:parameters:constructingBodyWithBlock:success:failure
is for multipart POST requests and its default serialized is not JSON.
Creates and runs an AFHTTPRequestOperation with a multipart POST request.
You want to use
POST:parameters:success:failure:
instead, as follows
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *request = #{#"email": self.email.text, #"password": self.password.text};
[manager POST:login parameters:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"DONE!");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed to log in: %#", operation.responseString);
}];
Try
- (AFHTTPRequestOperation *)POST:(NSString *)URLString parameters:(NSDictionary *)parameters success:(void ( ^ ) ( AFHTTPRequestOperation *operation , id responseObject ))success failure:(void ( ^ ) ( AFHTTPRequestOperation *operation , NSError *error ))failure
This method don't require the constructBody block. I don't think the block can be nil.