Differences between sending POST with AFNetworking and curl - ios

I
ve been using AFNetworking 2 with success for some time, but I stumbled upon case where I don't know where to turn my head to. I have to make POST request in order to log in, send credentials alongside and receive JSON back with operation status. For some weird reason sending it via AFNetworking like this:
NSDictionary *params = #{#"login": self.loginField.text, #"password" : self.passField.text};
NSDictionary *data = #{#"data": params};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
//manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:server parameters:#{#"data" : params} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", error);
}];
I have to pack dictionary with parameters as a single "data" parameter. I do get back OK 200, but if I take a look in server logs I see that no data was transferred, which ended up as user not recognized.
But if send with curl this:
curl -d 'data={"login":"xx", "password":"yy"}' http://someurl/api/login/
I got perfectly fine response and in logs I see some actual data. Does anyone know how to deal with such a case?
If it helps, I'm doing it in iPhone simulator, not tested on actual device.

If you have a look at the AFNetworking source code, namely the class AFJSONRequestSerializer, you will see that the serialise function for that serialiser puts the parameters you hand over into the body - and not as an HTTP parameter as you expect.
You should use an AFHTTPRequestSerializer in your case - that will add the parameters as (URL-encoded) HTTP parameters to your URL.
Something like that should work in your case:
// build the JSON parameter string
NSDictionary *params = #{#"login": self.loginField.text, #"password" : self.passField.text};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params
options:0
error:&error];
NSString *jsonString = [[NSString alloc] initWithBytes:[jsonData bytes]
length:[jsonData length]
encoding:NSUTF8StringEncoding];
// and now send the JSON parameter string as HTTP parameter
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager POST:server
parameters:#{#"data" : jsonString}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", error);
}];

Related

Unable to post JSON Using afnetworking in ios

I am getting this error while posting json to url :
Invalid top-level type in JSON write'
I am even sending perfect JSON using afnetworking post request code But it keeps giving me error.
My code :
NSString * serviceType = #"xyz";
NSString * remarks =#"project deadline is near ";
NSString * emailId = #"xyx.live.com";
NSDictionary *params =
# {
#"serviceType" :serviceType,
#"remarks" :remarks,
#"emailId" :emailId
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params
options:0
error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager2 = [AFHTTPRequestOperationManager manager];
AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
[serializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[serializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
manager2.requestSerializer = serializer;
[manager2 POST:#"http://xyx.com" parameters:jsonString success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON_post_fzzlogin: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//here is place for code executed in success case
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error while sending POST"
message:#"Sorry, try again."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
NSLog(#"Error: %#", error);
}];
Please help me out this regard .thanks in advance
You are trying to encode request twice because you set request serializer for AFHTTPRequestOperationManager and provide parameters as encoded JSON string. So you need to provide raw parameters if you want to use request serializer or don't use it and encode to JSON manually.
This is how you post JSON or rather NSDictionary by AFNetworking
NSDictionary *dict = #{#"Key":#"Value"};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:[Util urlAppend:kListOfArticleCatagory] parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *responseObj = (NSDictionary *)responseObject;//casting to NSDictionary from id
NSLog(#"%#",responseObj);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Something went wrong :%#",operation.responseString);
}];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
}
You dont post JSON through AFNetworking, rather the NSDictionary as the parameters, it will get converted to JSON as you post it.

AFNetworking not receiving response data

I am using AFNetworking to GET request by posting json object. But i am receiving empty value. I am using the following code.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *params = # {#"email" :user_name, #"password" :pass_word };
[manager GET:HOST_URL parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
NSDictionary *weather = (NSDictionary *)responseObject;
}
failure:
^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
NSLog(#"opstr%#",operation.responseString);
}];
What method i should use. If i use POST, i am getting error saying that "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.)
When i use GET i am getting response as empty. I am not sure where i am wrong.
Thanks in advance.
It means that your request response is not a valid json. You can correct the web service to return proper json. Or remove the following line
manager.requestSerializer = [AFJSONRequestSerializer serializer];
because it is converting response to json.
To allow fragments, change the code to following
[manager GET:HOST_URL parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
id json = [NSJSONSerialization JSONObjectWithData:responseObject
options:NSJSONReadingAllowFragments
error:&deserializingError];
NSLog(#"JSON: %#", responseObject);
NSDictionary *weather = (NSDictionary *)responseObject;
}
failure:
^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
NSLog(#"opstr%#",operation.responseString);
}];

how to post parameter like {"register_id":"3"} in AFNetworking

i tried it but didn't work in AFNetworking only showing parameters error
but i used postman to check and when i send data via key and value it showing error but from raw data i send {"register_id":"3"}
then it will show me data so how to post parameter like this in AFNetworking.
using This Link
http://www.icubemedia.net/visitorbook/display_all.php
is any one can help me for that how to post that data
log error is:
2015-06-19 14:05:08.078 DemoAFNetworking[72771:1160924]
{"msg":"parameter missing!"}
Indeed there are no parameters missing, the fact that the request worked in Postman was the key. On the one hand, you should be trying to POST to that URL, not GET. On the other hand, since you are sending a JSON, you need the appropriate serializer.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//JSON Serializer
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"register_id": #"3"};
[manager POST:#"http://www.icubemedia.net/visitorbook/display_all.php" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Check this example on how to do a GET with simple parameter with AFNetworking 2.0:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"foo": #"bar"};
[manager GET:#"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
EDIT 1: added JSON serializer ;)

JSON text did not start with array Error with AFNetworking

I am using the below code to use perform a GET request. In reverse manner am sending the params into server and data storing in the server fine. But am getting the error
* JSON text did not start with array *
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"emails": emailid,
#"password": paswrd,
#"gender": gende,
#"firstname":name1,
#"lastname":firstname1,
#"dateofBirth":dob1,
#"Country":count
};
[manager GET:#"http://37.187.152.236:91/EmployeeSvc.svc/AddEmployee?"
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
-(void) testHTTPS {
AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
[securityPolicy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setSecurityPolicy:securityPolicy];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:[NSString stringWithFormat:#"%#", HOST] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", string);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
You can check your serve Content-Type,If is text/html,you need code this:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
This problem can be due to bad JSON string. By Bad JSON string, I mean that your JSON response might not be starting with the expected characters i.e '[' or '{'. The starting characters must always be anyone of the above two.
Also there might be a chance that your JSON response is embedded in some kind of XML string. This happened to me and for me, it was just bad JSON response like I explained and I solved it by proper parsing.
Check this image. This is what bad JSON can look like.
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">
[{"Title":"DemoTitle","CreationDate":"06/06/2014","Description":"DemoDescription"}]
</string>
As you can see, JSON is embedded in XML string.**strong text**Also, check your JSON response on this site : http://jsonlint.com/
This will show you if the JSON you receive is valid for parsing or not.
Hope this helps.
This is the server side error when your server is not responding the JSON response OR Response is not a valid JSON because this error is appears when AF networking library unable to parse the JSON response.
Please check it with your server side about the response

AFNetworking 2.0: is it possible to put pure json in the body of a POST request?

I would like to make the following request from my app:
AFHTTPRequestOperationManager *requestManager = [[AFHTTPRequestOperationManager alloc] init];
requestManager.responseSerializer.acceptableContentTypes = [requestManager.responseSerializer.acceptableContentTypes setByAddingObject:#"application/json"];
requestManager.requestSerializer = [AFJSONRequestSerializer serializer];
[requestManager POST:urlString parameters:aParameters constructingBodyWithBlock:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"error: %#", error);
}];
Where aParameters is an NSDictionary with the following content:
NSDictionary *urlParams = #{#"username" : anUser.userName, #"password" : anUser.password};
When I make the request from my app with the user input of "anUsername" and "aPassword" I get the following log for the body in my servlet:
--Boundary+5738A89B2C391231
Content-Disposition: form-data; name="password"
aPassword
--Boundary+5738A89B2C391231
Content-Disposition: form-data; name="username"
anUsername
--Boundary+5738A89B2C391231--
multipart/form-data; boundary=Boundary+5738A89B2C391231
I was under the impression that using AFJSONRequestSerializer would send my request in the appropriate format, but as the log shows, it's multipart/form data. It is really hard (for me) to parse this kind of request (I'm parsing it in Java on the server side), so my question is: is it possible to send a json in the body of my request? Something like this:
{
"userName" : "anUsername",
"password" : "aPassword"
}
Any help would be appreciated.
For anyone concerned: Instead of using the POST:parameters:constructingBodyWithBlock:success:failure: method, you should use POST:parameters:success:failure:. The former performs a multipart form request, while the latter does url form encoding. Additionally, to send the params in JSON, the requestSerializer property of the AFHTTPRequestOperationManager instance should be an instance of AFJSONRequestSerializer (by default it is set to AFHTTPRequestSerializer)
It is really helpful to browse the implementation file of AFHTTPRequestOperationManager for details, it helped me sort this error out.
You don't need to send pure JSON in POST request, just send Parameters dictionary. Here is the sample code that is working for POST Request.
+ (void)login:(BOUser *)user responseBlock:(APIRequestResponseBlock)responseBlock {
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:#"%#login", BASE_URL_STRING];
NSDictionary *params = #{#"email": user.username,
#"password": user.password};
[manager POST:URLString parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
responseBlock(nil, FALSE, error);
}];
}
I hope it helps.

Resources