How to make a POST request in iOS? - ios

I am trying to figure out how to make use of AFNetworking 2.0. I am trying to POST a login with a username and password.
This is my current attempt but something is not working as it does not get sent.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"loginName": #"password"};
[manager POST:#"http://xxxx.com/login" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
NSLog(#"Data saved");
MainViewController *mainView = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
mainView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController: mainView animated:YES completion:nil];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
NSString *error_msg = (NSString *) error;
[self alertStatus:error_msg :#"Sign in Failed!" :0];
}];
}
} #catch (NSException * e) {
NSLog(#"Exception: %#", e);
[self alertStatus:#"Sign in Failed." :#"Error!" :0];
}
However nothing is happening, just keep getting this printout:
2014-04-16 20:14:09.903 Slidedrawer[9279:60b] 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=0x8e78bd0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
The response will be in JSON. Anyone know what I need to edit in the code or how to fix it?
JSON: {
"_id" = 533cb1c453769a02008c2d55;
name = dddd;
picture = "/img/users/default.jpg";
}
How do I access the above returned JSON, trying to pick apart each returned property to a string or integer etc...

Try this:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"userName": username, #"password": password};
manager.responseSerializer = [AFJSONResponseSerializer serializer]; // if response JSON format
[manager POST:#"http://asd.com/login.php" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error);
}];
For parsing the response use this the responseObject as NSDictionary:
NSString *userName = [responseObject objectForKey:#"userName"];
NSString *password = [responseObject objectForKey:#"password"];
Hope this helps.. :)

You may find Send Nested JSON using AFNetworking for the answer.
The error Error Domain=NSCocoaErrorDomain Code=3840 is received invalid JSON object from the server. It is probably caused by the server's improper handling your missing parameters . Your parameters dictionary has only one key object loginName.

Related

Value of NSMutableDictionary is not changing inside the block

I am passing the URL in this method and getting the data as output. i want to assign a new value to nsmutabledictionary but it is not assigning the value.
-(NSDictionary*) getDatafromURL: (NSString*)url{
__block NSMutableDictionary *returnData=[[NSMutableDictionary alloc] init];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
returnData=(NSMutableDictionary*)responseObject;
NSLog(#"Data 1: %#",returnData);// it is printing the data
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
NSLog(#"Data 2: %#",returnData);// it is not printing any data
return returnData;
}
in this above example the Data 1 is showing value successfully
Data 2 gives me empty dictionary.why it is not assigning the new value?
That happens because you get to the line with "Data 2" first and the block is executed only afterwards, since it is an async request. I would suggest that you change your method to something like:
- (void)getDataFromURL:(NSString *)url completionHandler:(void (^)(NSMutableDictionary *returnData, NSError *error))handler {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
returnData=(NSMutableDictionary*)responseObject;
NSLog(#"Data 1: %#",returnData);// it is printing the data
handler(returnData, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
handler(nil, error);
}];
}
There might be some compile errors in the code I provided.
The other solution would be to do a synchronous request, in which case the block would be executed before the code that is after the block.
EDIT:
If you are choosing the first solution, you have to continue using it asynchronously. So you would call it like:
[self getDataFromURL:#"abc.com" completionHandler:^ (NSMutableDictionary *returnData, NSError *error) {
// process your dictionary and the error object
}];
Please check whether your Data 2 is printing before data 1? If yes, its because, the response object gets downloaded only after a certain delay. Take away the return statements. Pass the data to the dictionary to which you return the method. For eg: like
instead of
self.myDictionary = [self getDatafromURL:someURl];
to
-(void) getDatafromURL: (NSString*)url{
__block NSMutableDictionary *returnData=[[NSMutableDictionary alloc] init];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
returnData=(NSMutableDictionary*)responseObject;
NSLog(#"Data 1: %#",returnData);// it is printing the data
self.myDictionary = returnData;
// Continue whatever you want to do
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Or use the dispatch methods instead of the blocks.
like
Or use manager waitUntilFinish method below.

OAuth Refresh Token Process for salesforce SDK

Can anyone help me with refreshing token on saleforce.
NSDictionary *fields = #{#"grant_type" : #"refresh_token",
#"refresh_token": oauth[#"refreshToken"],
#"client_id": coordinator.credentials.clientId,
#"format": #"json"
};
SFRestRequest *request = [SFRestRequest requestWithMethod:SFRestMethodPOST path:[NSString stringWithFormat:#"%#/services/oauth2/token",[SFAccountManager loginHost]] queryParams:fields];
request.endpoint = [NSString stringWithFormat:#"%#/services/oauth2/authorize", [SFAccountManager loginHost]];
[[SFRestAPI sharedInstance] sendRESTRequest:request failBlock:^(NSError *e) {
NSLog(#"Error %#", e);
} completeBlock:^(NSDictionary* dict) {
NSLog(#"dict");
}];
This is what i am trying to do, but i am getting the following error:
Error Domain=NSURLErrorDomain Code=404 "The operation couldn’t be completed. (NSURLErrorDomain error 404.)" UserInfo=0x7993c670 {Transfer-Encoding=Identity, Content-Type=text/html;charset=UTF-8, Date=Thu, 13 Nov 2014 15:23:36 GMT}
I am not sure what is going wrong.
FYI: Understanding the OAuth Refresh Token Process
This is the request:
endpoint: test.salesforce.com/services/oauth2/authorize
method: POST
path: test.salesforce.com/services/oauth2/token
queryParams: {"grant_type":"refresh_token","refresh_token":"5AsdfdfssdBuiV6yFNukUqDSMUH1tnk39L.x0GFcdqdMhpmQUTu.wv1BNndfglD3SxEZIFUev4i8T2KLkcCOK","format":"json","client_id":"3MVG9dPGzsddfssfdsOQG3p9KW.2hh3Bh5BeEsdfsRlDhxcybG.YRTQC0C0XayvzEw.5.umftLwJpYjYVDE6xgSCgXo"}
I stopped using Salesforce and NSURL Kit instead i use AFHTTPREQUEST
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"password" forKey:#"grant_type"];
[dict setObject:#"xxx" forKey:#"client_id"];
[dict setObject:#"xxx" forKey:#"client_secret"];
[dict setObject:#"your user" forKey:#"username"];
[dict setObject:#"password" forKey:#"password"];
[dict setObject:#"json" forKey:#"format"];
[manager POST:#"https://test.salesforce.com/services/oauth2/token" parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
}];

handling the Response with the AFNetworking 2

i am really new to IOS development. i want to develop an application which is dealing with some web services and display in a table view. somehow i found a 3rd party library for do the networking stuffs [AFNetworking 2]. below is my code to get the json response for any given url and parameters.
-(NSDictionary*)getWebServiceResponce:(NSString *)url :(NSDictionary *)object
{
// NSDictionary *parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"47", #"caregiverPersonId", nil];
__block NSDictionary* result=Nil;
__block NSString* person=Nil;
AFSecurityPolicy *policy = [[AFSecurityPolicy alloc] init];
[policy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager setSecurityPolicy:policy];
operationManager.requestSerializer = [AFJSONRequestSerializer serializer];
operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
[operationManager POST:url
parameters:object
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", [responseObject description]);
person = [responseObject[#"d"]objectForKey:#"PersonId"];
// [self returnedResponce:responseObject];
result = (NSDictionary *) responseObject[#"d"];
NSLog(#"RESULT: %#", result);
NSLog(#"personm: %#", person);
[operation waitUntilFinished];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error description]);
//result = [error];
}
];
return result;
}
this code works perfectly.. but my point is when i put some breakpoints to check what are the values i got for several variables, it shows null. but my log shows the entire json response.
and i want to return my response object as a dictionary. because i want to do some process with the response.. can some one help me with this ?
The problem is that result is nil when it gets returned. AFNetworking uses ObjC's awesome blocks, they get executed asynchronously. Read more about it here.
You should include a callback block in your getWebServiceResponce method. I've thrown together a bit of code but you should really read more about blocks.
-(void)webServiceResponceForURL:(NSString *)url dictionary:(NSDictionary *)object success:(void (^)(NSDictionary *responseObject))success {
// NSDictionary *parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"47", #"caregiverPersonId", nil];
__block NSDictionary* result=Nil;
__block NSString* person=Nil;
AFSecurityPolicy *policy = [[AFSecurityPolicy alloc] init];
[policy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager setSecurityPolicy:policy];
operationManager.requestSerializer = [AFJSONRequestSerializer serializer];
operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
[operationManager POST:url
parameters:object
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", [responseObject description]);
person = [responseObject[#"d"]objectForKey:#"PersonId"];
// [self returnedResponce:responseObject];
result = (NSDictionary *) responseObject[#"d"];
NSLog(#"RESULT: %#", result);
NSLog(#"personm: %#", person);
//We are executing the block as soon as we have the results.
if (success) {
success(responseObject);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", [error description]);
//result = [error];
}
];
}
Edit:
[self webServiceResponceForURL:#"foo://foo" dictionary:nil success:^(NSDictionary *responseObject) {
//your code here
}
[self webServiceResponceForURL:#"foo://foo" dictionary:nil success:^(NSDictionary *responseObject) {
//your code here
}
Here you will got complete responseObject in form NSDictionary. You can assign responseObject to instance variable. Now This instance Variable will be used at point time. in your case, it will passed on button event.

how to send EmailId or Device token as parameter using AFNetworking with AFHTTPRequestOperationManager

I need to send an email ID to a server to reset this email address using AFNetworking.
SSAFRequest *afm= [[SSAFRequest alloc]init];
NSDictionary *params = #{#"email": #"a#b.com"};
[afm AfRequest_POST_Params:urlWithQuerystring urlWithQuerystring:urlWithQuerystring params:params :^(id JSON, NSError *error) {
if(JSON!=Nil && ![JSON isEqual:[[NSNull alloc]init]]) {
}];
This is my AFNetworking code:
-(void)AfRequest_POST_Params:(NSString *)baseUrl urlWithQuerystring:(NSString *)urlstring params:(NSDictionary *)parameters:(void (^)(id result, NSError *error))block {
NSLog(#"AfRequest_POST_Params ----%# %#",baseUrl,urlstring);
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager manager]initWithBaseURL:[NSURL URLWithString:baseUrl]];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager POST:baseUrl parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject){
NSLog(#"****Success****");
block(responseObject,nil);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error.localizedDescription);
block(nil,error);
}
];
}
But I don't know what I am missing in my code. This is the error I am getting:
<0x16d95210 SSLoginViewController.m:(821)> Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x16ec5cd0 {NSDebugDescription=Invalid value around character 0.}
please suggest me on this, Thanks in advance.

Cocoa Error 3840 when POST Request with AFNetworking 2

I call this function and return Cocoa Error 3840 every time.
I try to debug and fix it and it error when request rather than when parse the result
I found this error in failure blocks when request.
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=0x109230960 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not et.}
2013-11-01 12:09:30.925 MagicBox[87431:70b] The operation couldn’t be completed. (Cocoa error 3840.)
That's my code
Thanks in Advance.
- (void)loginWithUserName:(NSString *)userName
Password:(NSString *)password
orFacebook:(NSString *)facebookID
withResponseBlock:(ResponseBlock)responseBlock {
if (!userName && !facebookID) {
NSError *error = [NSError errorWithDomain:#"Missing Parameters"
code:400
userInfo:#{ NSLocalizedDescriptionKey : #"Username or FacebookID is required"}];
responseBlock(error, nil);
}
NSDictionary *params;
if (facebookID) {
params = #{ #"fb_id": facebookID };
} else {
params = #{ #"username": userName,
#"password": password };
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *loginURL = [self requestWithPath:#"/api/login"];
[manager POST:loginURL
parameters:params
constructingBodyWithBlock:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (responseBlock) {
responseBlock(nil, responseObject);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (responseBlock) {
responseBlock(error, nil);
}
}];
}
I solved it by adding following line of code
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
Had been stuck with the same problem.
I solved it by this:
self.requestSerializer = [AFJSONRequestSerializer serializer];
i.e. double check whether the AFHTTPRequestOperationManager uses correct request serializer.
Hope this can help you!
I solved this by making sure the returned data is in the correct serialization with google spreadsheets XML response (instead of JSON)
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
I solved it by adding following line of code
manager.requestSerializer = [AFJSONRequestSerializer serializer];

Resources