How to determine reason for failure with AFNetworking AFJSONRequestOperation - iphone

I've inherited a project and am implementing AFNetworking and reading the docs it sounds great and much simpler than the current code. I have a url with json data so I'm doing the following, but getting the failure block and no idea why. I'm sure it's there, but how can I dig into AF and log the responses to determine failure reason. I know the url works, but perhaps its hitting the url but having trouble parsing?
NSString *listURL = [NSString stringWithFormat:GET_LIST,BASE_URL];
NSURL *url = [NSURL URLWithString:briefListURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest: request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.list = [NSArray arrayWithArray:(NSArray *)JSON];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
[self listOperationDidFail];
}];

thanks to #Larme this worked:
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(#"Error: %#", error); }
also, to answer my own issue above with text/plain. just add this before setting up operation:
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/plain"]];

Related

Accessing POST wcf services from iPhone

I have been given url of an asp.net wcf service page which accepts few parameters as POST. But I am getting error code 400 when I try to access it.
url:
http://domain.w04.wh-2.com/IBServiceHost/IBService.svc/AddTask
I am also told to post json as below
{
"TaskId":"23",
"TaskDate":"6/27/2013",
"TaskDesc":"Test task",
"TaskName":"TestName",
"TaskStatus":true,
"ProjectId":"24",
"DbState":"Added"
}
My code to access the service:
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://mydomain.w04.wh-2.com"]];
client.parameterEncoding = AFJSONParameterEncoding;
NSMutableURLRequest *request =
[client requestWithMethod:#"POST" path:#"/IBServiceHost/IBService.svc/AddTask" parameters:dictTask];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSLog(#"JSON: %#", [JSON valueForKeyPath:#"LoginResult"]);
NSLog(#"Code: %#", [[[JSON valueForKeyPath:#"LoginResult"] valueForKeyPath:#"Code"] stringValue]);
NSLog(#"FaultString: %#", [[JSON valueForKeyPath:#"LoginResult"] valueForKeyPath:#"FaultString"]);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
{
NSLog(#"request %#",request);
NSLog(#"response %#",response);
NSLog(#"error %#",error);
NSLog(#"error opening connection");
}];
[operation start];

Waiting for AFJSONRequestOperation to complete

I'm working with AFNetworking to get some JSON from the web. How can I get the response from the asynchronous request returned? Here's my code:
- (id) descargarEncuestasParaCliente:(NSString *)id_client{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://whatever.com/api/&id_cliente=%#", id_client]]];
__block id RESPONSE;
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
RESPONSE = JSON;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"ERROR: %#", error);
}];
[operation start];
return RESPONSE;
}
I think you are confused about how blocks work.
That's an asynchronous request, therefore you cannot return any value computed inside the completion block, since your method already returned when it's executed.
You have to change your design an either perform a callback from inside the success block, or pass your own block and get it called.
As an example
- (void)descargarEncuestasParaCliente:(NSString *)id_client success:(void (^)(id JSON))success failure:(void (^)(NSError *error))failure {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://whatever.com/api/&id_cliente=%#", id_client]]];
__block id RESPONSE;
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
if (success) {
success(JSON);
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"ERROR: %#", error);
if (failure) {
failure(error);
}
}];
[operation start];
}
You will then call this method like follows
[self descargarEncuestasParaCliente:clientId success:^(id JSON) {
// Use JSON
} failure:^(NSError *error) {
// Handle error
}];

AFNetworking Expected content type error

I am getting the json string in failure block
NSURL *url = [[NSURL alloc] initWithString:#"http://www.vinipost.com/Services/Update/UpdateService.asmx/GetPropSubType?"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/html"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
Output:
Request Failed with Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Expected content type {(
"text/json",
"text/javascript",
"application/json",
"text/html"
)}, got text/plain" UserInfo=0x71521a0 {NSLocalizedRecoverySuggestion=[{"PropTypId":1,"PropCatId":1,"PropTyp":"Flat/ Condo"}.......**
You need to add this line before operation
[AFJSONRequestOperation addAcceptableContentTypes:
[NSSet setWithObject:#"text/plain"]];
The error is clear:
the web service is returning a wrong content type.
The content type should be one of these:
"text/json",
"text/javascript",
"application/json",
"text/html"
But it returns
text/plain
Moreover, if you look at the http response, it returns HTML TAGS inside it, so AFNetworking is not able to parse.
If this page:
http://www.vinipost.com/Services/Update/UpdateService.asmx/GetPropSubType?
is under your control, correct the behavior removing html tags and changing the content type
In AFNetworking, you have to create NSURLRequest with the help of AFHTTPClient(So first you have to create AFHTTPClient and have to set some properties for this object) like below
AFHTTPClient *httpClient = [[httpClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://www.vinipost.com/"]];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
httpClient.parameterEncoding = AFJSONParameterEncoding;
now if depends of GET/POST or any other type request you need to set parameter I consider it as POST Request, so set the Parameter dict and set all required Key Value pairs properly.if no parameters required you can pass Parameters as nil
NSURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"Services/Update/UpdateService.asmx/GetPropSubType?" parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSLog(#"%#",JSON);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
{
NSLog(#"Error MSG = %#",error);
}];
[operation start];
hope this will work for you :)

AFJSONRequestOperation with JSON encoded as NSISOLatin1StringEncoding crashing

I want to use AFNetworking more specifically AFJSONRequestOperation in a project to allow for easy async calls. I quickly tried using the sample code from AFNetworking GitHub Page
NSURL *url = [NSURL URLWithString:#"https://alpha-api.app.net/stream/0/posts/stream/global"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"App.net Global Stream: %#", JSON);
}
failure:nil];
[operation start];
Which works fine, But when I use the URL for MetOffice Datapoint it crashes, I believe this might be because of the encoding type of the JSON feed being NSISOLatin1StringEncoding which causes a problem with NSJSONSerialization
The way I currently handle this is
NSString *string = [NSString stringWithContentsOfURL:kMetOfficeAllSites encoding:NSISOLatin1StringEncoding error:&error];
NSData *metOfficeData = [string dataUsingEncoding:NSUTF8StringEncoding];
id jsonObject = [NSJSONSerialization JSONObjectWithData:metOfficeData options:kNilOptions error:&error]
But how do I handle this situation with AFJSONRequestOperation?
Thanks in Advance

Getting user's information after OAuth login

I want to get user's info. After OAuth I send this request:
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1/account/verify_credentials.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Public Timeline: %#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"error = %#", error);
NSLog(#"json = %#", JSON);}];
[operation start];
But got an error: {"error":"Could not authenticate you.","request":"\/1\/account\/verify_credentials.json"} Why I can't get access to information even after login in?
You haven't attached the OAuth token to the request. You're just sending a request with that URL string.
You might to have a look AFOAuth2Client which provides a neat extension to AFNetworking for doing authorized requests on Twitter.
Alternatively, you can use the built in iOS 5+ Twitter API, I wrote an answer for another SO post that shows you how exactly to do this - and it's super easy :)
If you need to implement OAuth from scratch, please see: https://github.com/bengottlieb/Twitter-OAuth-iPhone/
Good luck!