Stuck with AFNetworking - ios

Am unable to find the real problem with my code. Am using the same code for all other APIs and everything working fine but one API is giving problem.
NSString *strUrl = [[NSString stringWithFormat:#"%#%#",baseURL,apiURL] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
//request type may be "POST" or "GET"
[request setHTTPMethod:requestType];
[request setValue:secretKey forHTTPHeaderField:key];
//contentType may be "application/json" or "text/html"
[request setValue:contentType forHTTPHeaderField:#"Accept"];
[request setValue:contentType forHTTPHeaderField:#"Content-Type"];
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
requestOperation.responseSerializer = [AFJSONResponseSerializer serializer];
[requestOperation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
completion(nil);
}];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) {
completion(nil);
} failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {
completion(nil);
}];
This code is working for all APIs except one. It's giving me this error in error block.
Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html"
I have then tried to add the acceptable content type by doing this.
requestOperation.responseSerializer.acceptableContentTypes = [requestOperation.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
This did not work. Then i changed the response serializer to AFHTTPResponseSerializer and removed the acceptable content types line. Then the response came as NSData and I parsed the NSData response to JSON object for all other APIs. But this API is giving this error after changing the response serializer. Here is the error from error block.
JSON text did not start with array or object and option to allow fragments not set.
Am not getting this why this happening. I have tried to change the header acceptable content type to json and html. But those are not making any difference. I have tried the API in Chrome Postman and it's working absolutely fine. Please suggest something, where am doing wrong.

Set Content-type to application/Json and try
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];

Related

how to test if json data got to a server ios

Im trying to send some json data to a http server in my ios app, but I dont know how to verify if data got there... For testing Im using http://www.jsontest.com/.
NSURL *url = [NSURL URLWithString:#"http://validate.jsontest.com"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPBody:createJson()]; //createJson() is my function which pass json data
encoding:NSUTF8StringEncoding]);
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://validate.jsontest.com"]]; //by this I want to open json site in browser and see if data come. - but something different should be here I guess
So... How should I change my code to see data from createJson() in browser? Are there any mistakes in code so data arent even sent to a server?
Thank you for any help.
I recommend using AFNetworking
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
That you have 2 blocks one runs on success & other on failure.
This is the link on Github
https://github.com/AFNetworking/AFNetworking

How to get returned object on http 422 response on AFNetworking?

I am using AFNetwoking v 2.2.4 as a networking library on iOS. It assumes non http 2xx (http 200 as success ) response as error and throws on error block like this:
NSError *error= nil;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:user options:NSJSONWritingPrettyPrinted error:&error];
NSString *connectionString = [NSString stringWithFormat:#"%#%#",SERVER_URL, RESOURCE_URL_USER_SIGNUP];
NSURL *url = [NSURL URLWithString:connectionString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:jsonData];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"response object: %#", (NSDictionary *)responseObject);
[delegate userSignUpCompletedWithResponse:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
[delegate userSignUpFailedWithError:error];
NSString *errorBodyMessage = [[error userInfo] objectForKey:#"NSLocalizedRecoverySuggestion"];
NSLog(#"error message: %#", errorBodyMessage);
}];
[operation start];
Here, everything is working as expected when http response is 200. I have a REST API on server side which is written in ROR. For the user sign up, if all fields have valid values then it sends 200 status, but if data are invalid, such as email already taken; In this case server sends 422 status with error message in JSON. I need to trace error message and show it to mobile user but I am unable to get the message object in error block. I have logged entire error but did not find the object returned form the server. How can I get the JSON object while there is non 2xx http response using AFNetworking?
Access the responseObject property of the operation passed into the failure block.
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"JSON: %#", operation.responseObject);
}];

AFNetworking version 2 content-type error

I'm attempting to make an iphone app that will interact with a particular JIRA server. I've got the following code to log in:
NSURL *url = [[NSURL alloc] initWithString:#"https://mycompany.atlassian.net/rest/auth/latest/session/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"{\"username\":\"%#\",\"password\":\"%#\"}", username, password];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept" ];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"ERROR: %#", error);
}
];
[operation start];
But it's giving me the following error having to do with Content-Type:
ERROR: Error Domain=AFNetworkingErrorDomain Code=-1011
"Request failed: unsupported media type (415)"
UserInfo=0x8cd6540
{
NSErrorFailingURLKey=https://mycompany.atlassian.net/rest/auth/latest/session/,
NSLocalizedDescription=Request failed: unsupported media type (415),
NSUnderlyingError=0x8c72e70
"Request failed: unacceptable content-type: text/html",
I'm not sure what the problem is. I found this question, which I thought might be a similar problem, but the answers say to either use the AFJSONRequestOperation class (which I can't because I'm using AFNetworking version 2, which doesn't have that class), or to fix it on the server side (which I also can't for obvious reasons).
What can I fix this error when I can't fix the server side and I can't use AFJSONRequestOperation?
If using AFNetworking 2.0, you can use the POST method, which simplifies this a bit:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"username":username, #"password":password};
[manager POST:#"https://mycompany.atlassian.net/rest/auth/latest/session/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
This does the creation of the request, setting its Content-Type according to the requestSerializer setting, and encodes the JSON for you. One of the advantages of AFNetworking is that you can get out of the weeds of constructing and configuring NSURLRequest objects manually.
By the way, the "Request failed: unacceptable content-type: text/html" error means that regardless of what you were expecting to receive (e.g. JSON), you received HTML response. This is very common: Many server errors (e.g. the server informing you that the request was malformed, etc.) generate HTML error messages. If you want to see that HTML, in your failure block, simply log the operation.responseString.
It turns out the problem is that this one line:
[request setValue:#"application/json" forHTTPHeaderField:#"Accept" ];
Should be
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type" ];
The error is now solved. (Edit: I should have both, see CouchDeveloper's comment.)
EDIT
Rob's solution is better, so I'm going with it. I had actually tried a similar solution to what he shows, but where he had the line,
manager.requestSerializer = [AFJSONRequestSerializer serializer];
I had the line:
[manager.requestSerializer
setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
...which didn't work. Kudos to Rob for getting it to work!
I had the same problem in AFNetworking 2.0 and the solution was that I had to make sure I set the AFHTTPRequestSerializer type (In case your request is JSON) the it should be like this.
AFHTTPSessionManager *myHTTPManager = ...
[myManager setRequestSerializer:[AFJSONRequestSerializer serializer]];
You have to set both AFHTTPResponseSerializer and AFHTTPRequestSerializer
if you are using default written class AFAppDotNetAPIClient and you face this error. Must add responseSerializer. see your shared method should look like -
+ (instancetype)sharedClient {
static AFAppDotNetAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
_sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
_sharedClient.responseSerializer = [AFHTTPResponseSerializer serializer];
});
return _sharedClient;}
Use this line of code.
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];

IOS - Same ASIHTTPRequest code doesn't work only one method

In my project I make the other functions work with this code. But for this method I cannot make it work. I did copy-paste all this code for different methods(changing URL ,Result). The parameters of this methods are only int and string.
I always correct the wcf method from SOAP UI and .NET project.It works correct.
I only cannot make this code work for this method.
The [request responseString] returns a patient's information. Please help me. Thank you.
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:HASTAARAIP]];
NSData *myPostData = [[NSString stringWithFormat:#"{\"kat\":0,\"oda\":0,\"hastaAdi\":\"KAI\",\"protokolNo\":0,\"yatanAyaktan\":1}"] dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *myMutablePostData = [[NSMutableData alloc]initWithData:myPostData];
[request setPostBody:myMutablePostData];
[request setRequestMethod:#"GET"];
[request addRequestHeader:#"Content-Type" value:#"application/json"];
[request setDelegate:self];
[request startSynchronous];
Here is some things that can make you understand.
With this code the [request responseString] and [request responseStatusMessage] is null. But if I remove the line where the addRequestHeader, it says for responseStatusMessage HTML/1.1HTTP/1.1 404 Not Found 404. I didn't understand why it gives this 404 error. This request type works for the other methods.
The ıp is like http://.../rest/<methodname>
Added log for a part of responsestring`:
The server encountered an error processing the request. The exception
message is 'The incoming message has an unexpected message format
'Raw'. The expected message formats for the operation are 'Xml';
'Json'. This can be because a WebContentTypeMapper has not been
configured on the binding. See the documentation of
WebContentTypeMapper for more details.'. See server logs for more
details. The exception stack trace is:
Updated:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:HASTAARAIP]];
[request setPostValue:#"0" forKey:#"kat"];
[request setPostValue:#"0" forKey:#"oda"];
[request setPostValue:#"KAI" forKey:#"hastaAdi"];
[request setPostValue:#"0" forKey:#"protokolNo"];
[request setPostValue:#"1" forKey:#"yatanAyaktan"];
[request startSynchronous];
But for responseString the logs:
The server encountered an error processing the request. The exception message is 'The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details. The exception stack trace is:
Trying with AFNetworking:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"kat": #"0",#"oda": #"0", #"hastaAdi":hastaAdi, #"protokolNo":#"0",#"yatanAyaktan":#"1"};
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[manager POST:HASTAARAIP parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
But the log is like this:
Error: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x8e49ce0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
ASI was long abandoned by the developer. using AFNetworking 2.0 will be more easy, and with a lot of good documentation: https://github.com/AFNetworking/AFNetworking
it looks like you are trying to make a #"POST" request.
you can use the following code snippet (uses IOS build in classes) to make the request:
NSDictionary *parameters = #{#"key" : value};
/* the following serialization is NOT a deep serialization */
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
NSURL *url = [NSURL URLWithString:#"http://www.someURL.com/whatEver"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0f];
[request setHTTPMethod:#"POST"];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:jsonData];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(#"all headers from response:%#", [httpResponse allHeaderFields]);
NSLog(#"status code from response:%ld", (long)[httpResponse statusCode]);
}
}];

NSURLRequest HTTPBody vs. ASIHTTPRequest postBody

I'm trying to convert most of a project's NSURLRequests that use NSURLConnection to ASIHTTPRequest calls. I came across an issue about setting the HTTPBody in an ASIHTTPRequest. Here's what I had for the NSURLRequest call:
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]];
[req setHTTPMethod:#"POST"];
[req setHTTPBody:[self.paramString dataUsingEncoding:NSUTF8StringEncoding]];
[self _sendRequest:req];
And to convert to ASI, this is what I have so far:
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:self.urlString]];
[request setRequestMethod:#"POST"];
[request appendPostData:[self.paramString dataUsingEncoding:NSUTF8StringEncoding]];
[request setCompletionBlock:^{
NSLog(#"ASIHTTP request finished: %#", [request responseString]);
// Do stuff here
}];
[request setFailedBlock:^{
NSError *error = [request error];
NSLog(#"ASIHTTP error: %#", [error description]);
}];
[request startAsynchronous];
Although when I run this with ASI, I get this error:
ASIHTTP error: Error Domain=ASIHTTPRequestErrorDomain Code=6 "Unable to start HTTP connection" UserInfo=0x10ddf6b0 {NSLocalizedDescription=Unable to start HTTP connection}
EDIT This error was fixed, but data is still not being transmitted correctly due to the body not being set.
I'm thinking this has to do with me not setting the body correctly. I tried using ASI's setPostBody, but that only produced the same result. This works fine with NSURLRequest, but not ASI. I'm pretty sure it's really simple and I just haven't explored ASI's full library quite yet, but I was just wondering if anyone had any suggestions. I have read the documentation, but I couldn't find what I was looking for.
Thanks!
Could you check that
self.paramString
is correct? How does it look like?
I ended up using ASIFormDataRequest and setting values and keys. That seemed to work!

Resources