What am I doing wrong with this AFNetworking JSON Post? - ios

I have an odd problem... I'm doing this ios http/json post using AFNetworking against a rails server and the expected output is something like:
{"success":true,"auth_token":"4D8CyUsyGZdqo6X1TCeq"}
Sometimes it works as expected, but often on the rails side the request is not detected as a "JSON" request so it serves up HTML. Anyone have an idea on this? Is there something I'm doing wrong with regards to setting up the JSON request?
NSDictionary *parameter = #{#"email":#"philswenson#mymail.com", #"password":#"mypassword"};
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://localhost:3000"]];
[httpClient setParameterEncoding:AFJSONParameterEncoding];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient postPath:#"api/v1/sessions" parameters:parameter success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *jsonString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Here is what we got %#", jsonString);
NSDictionary *loginResult = [jsonString objectFromJSONString];
NSNumber* success = [loginResult objectForKey:#"success"];
NSLog(#"success = %#", success);
NSLog(#"yay");
// sample output:
// {"success":true,"auth_token":"4D8CyUsyGZdqo6X1TCeq"}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self handleConnectionError:error];
}];

I know with my service, I need to add application/jsonrequest for accept to my parameters like this:
NSDictionary *parameter = #{#"email":#"philswenson#mymail.com", #"password":#"mypassword", #"accept:application/jsonrequest"};
The AFJSONParameterEncoding only tells it to send the parameters in a JSON file. I need to send a parameter to tell it how to send the data back.

Add:
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];

I tried the suggestions - no dice.... the setDefaultHeader actually caused a crash (whatever the iOS term is for access violation)...
The "accept:application/jsonrequest"} didn't see any difference...
I ended up using this code:
NSDictionary *parameter = #{#"email" : #"phil#gmail.com", #"password" : #"mypw", #"format":#"json"};

Related

how to handle space in sending json parameters to server in ios?

I am sending data to the server it is going successful but response coming with %20 at the space in data what I have sent to server here is the code I am using
NSString *str = [NSString stringWithFormat:#"http://www.me911.com/new/miphone3/android_edithealth.php?profile_id=%#&health_condition=%#&health_insurance_provider=%#&primary_physician_name=%#&primary_physician_phone=%#&last_physical=%ld&blood_type=%#&organ_donor=%#",profileId,txthospital.text,textinsurence.text,txtprimary.text,txtphone.text,dateInMillis,questionNo,textorgan.text];
str = [str stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSLog(#"Healthinfo URL: %#",str);
NSMutableURLRequest *dataRqst = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:str] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
[dataRqst setHTTPMethod:#"POST"];
NSString *stringBoundary = #"0xKhTmLbOuNdArY---This_Is_ThE_BoUnDaRyy---pqo";
NSString *headerBoundary = [NSString stringWithFormat:#"multipart/form-data; boundary=%#",stringBoundary];
[dataRqst addValue:headerBoundary forHTTPHeaderField:#"Content-Type"];
NSMutableData *postBody = [NSMutableData data];
[dataRqst setHTTPBody:postBody];
NSHTTPURLResponse *dataresponse =[[NSHTTPURLResponse alloc] init];
NSError* error = [[NSError alloc] init] ;
//synchronous filling of data from HTTP POST response
NSData *responseData = [NSURLConnection sendSynchronousRequest:dataRqst returningResponse:&dataresponse error:&error];
//convert data into string
NSString *responseString = [[NSString alloc] initWithBytes:[responseData bytes] length:[responseData length] encoding:NSUTF8StringEncoding];
NSLog(#"responseString %# ",responseString);
if (responseString == NULL)
{
NSDictionary *infoDic = [[NSDictionary alloc] initWithObjectsAndKeys:#"There was a small problem",
#"title",
#"The network doesn't seem to be responding, please try again.",
#"message",
#"OK",
#"cancel",
#"1",
#"tag",nil,
#"delegate", nil];
[CommonFunctions performSelectorOnMainThread:#selector(showAlertWithInfo:) withObject:infoDic waitUntilDone:NO];
}
else
{
NSDictionary *jsonResponse = [responseString JSONValue];
if ([jsonResponse objectForKey:#"error"]){
NSLog(#"response %#",jsonResponse);
}
else{
}
NSMutableArray *dataresponse=[jsonResponse valueForKey:#"success"];
if ([jsonResponse objectForKey:#"success"])
{
NSLog(#"Array response %#",dataresponse);
}
}
And this is web service
:http://anaadit.net/miphone3/android_edithealth.php?profile_id=287&health_condition=palo%20Alto%20Veterans%20Hospital%20&health_insurance_provider=Blue%20Cross&primary_physician_name=Dr.Akki&primary_physician_phone=6504935000&last_physical=-57600&blood_type=7&organ_donor=No
Here I am sending data in textfield in like guru prasad but response getting like this guru%20prasad.
So please correct me where am I going wrong .
thanks in advance
Your code has a number of issues.
In order to create a URL with query params, I recommend to use the utility class NSURLComponents (see Apple documentation: NSURLComponents).
Composing a POST request whose content type is "multipart/formdata" is quite error prone. If you absolutely have to compose such a request I very strongly recommend to use a Network Library, for example AFNetworking.
On the other hand, using a POST request whose Content-Type is application/json is very easy to setup, especially with NSURLSession and friends.
You can find specific solutions for any of the suggested approaches mentioned above on SO, too.
Its seems there is some problem in parsing data, the space are replaced with %20...It seems you are using NSURL Connection for making API Calls.
Use AFNetworking for making API Calls, the response data will automatically come in JSON format and you can initialize Dictionary from same.
Please find below link for AFNetworking:
https://github.com/AFNetworking/AFNetworking
Please use "AFNetworking" and the code will be:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"profile_id": #"287", #"health_condition": #"palo Alto Veterans Hospital", #"health_insurance_provider": #"Blue Cross",
#"primary_physician_name":#"Dr.Akki",
#"primary_physician_phone":#"6504935000",
#"last_physical":#"-57600",
#"blood_type":#"7",
#"organ_donor":#"No"};
[manager POST:#"http://anaadit.net/miphone3/android_edithealth.php" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Please try the above code. I think this will help you.

how to send array as a parameter in Afnetwoking post method?

hi i need to send a array as a one of the parameter in Afnetworking Query String
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://192.008.0.28/aaa/a/"]];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: #"20", #"Miles", [NSArray arrayWithObjects:#"1",#"2",#"3",nil], #"Interval", nil];
[httpClient postPath:iUpdateNotificationMethod parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
But server side we got "Miles":20,"Intervals":null how to fix it
Thanks,
Try This
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:OAuthBaseURL];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] initWithCapacity:0];
for (int i =0; i < [userIDs count]; i++) {
NSString *userID = [[userIDs objectAtIndex:i] objectForKey:#"id"];
NSDictionary *tmpDict = [NSDictionary dictionaryWithObjectsAndKeys:userID , [NSString stringWithFormat:#"ids[%i]",i], nil];
[parameters addEntriesFromDictionary:tmpDict];
}
[client postPath:#"/user"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSData *data = (NSData *)responseObject;
NSString *jsonStr = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(#"jsonStr %#",jsonStr);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self showError];
}
];
Since you're submitting an array, AFNetworking is generating a different parameter name and overloads it with the values you supply. For example, your request generates the following querystring:
Interval[]=1&Interval[]=2&Interval[]=3&Miles=20
This is defined in AFHTTPClient.m in the AFQueryStringPairsFromKeyAndValue function.
If you want to keep the original parameter, you should decide how to convert your NSArray to NSString by yourself. For example, you can do something like [myArray componentsJoinedByString:#","] and then split it back to elements on the server. If you choose this method, beware of using characters that might appear in your actual data.
I believe this will work:
params = #{ #"Miles": #"20", #"Interval": #[#"1",#"2",#"3"] };

AFNetworking returning NSCFData; issue with registerHTTPOperationClass [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am new to AFNetworking and am making a call to a simple login api that returns json like:
{"status":"success","data":{"auth_token":"12jt34"}}
I'm doing it via the following but it is returning __NSCFData rather than something that I can manipuate.
NSURL *baseURL = [NSURL URLWithString:#"http://localhost:3000/arc/v1/api/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
uname,#"email", pwd, #"password",
nil];
[httpClient postPath:#"login-mobile" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *className = NSStringFromClass([responseObject class]);
NSLog(#"val: %#",className);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
and it outputs:
2013-03-21 14:52:51.290 FbTabbed[21505:11303] val: __NSCFData
but I'd like it for it to be a dictionary that I can manipulate which is how I think it is supposed to work? What am I doing wrong?
[httpClient defaultValueForHeader:#"Accept"];
should be:
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
Yes, responseObject is a NSData. You can then parse it into a dictionary or array using NSJSONSerialization method JSONObjectWithData:
NSURL *baseURL = [NSURL URLWithString:#"http://localhost:3000/arc/v1/api/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient defaultValueForHeader:#"Accept"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
uname,#"email", pwd, #"password",
nil];
[httpClient postPath:#"login-mobile" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSAssert([responseObject isKindOfClass:[NSData class]], #"responseObject is supposed to be a NSData"); // it should be a NSData class
NSError *error;
self.results = [NSJSONSerialization JSONObjectWithData:responseObject
options:0
error:&error];
if (error != nil)
{
// handle the error
// an example of the sort of error that could result in a parse error
// is if common issue is that certain server errors can result in an
// HTML error page (e.g. you have the URL wrong, your server will
// deliver a HTML 404 page not found page). If you want to look at the
// contents of the `responseObject`, you would:
//
// NSLog(#"responseObject=%#", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
}
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error retrieving data: %#", error);
}];
Obviously, your results object would be a NSDictionary or NSArray, depending upon the type of response you get from your API.
What am I doing wrong?
NSStringFromClass() returns the name of the class you pass in as an NSString object.
If you want to make a dictionary out of the returned JSON string, then you have to parse it, for example using the NSJSONSerialization class.

AFHttpclient get json body in block but outer function returns null

I am trying to send post request on some url and in body to be only json data (trying to register new user sending json like
{
"username": "test",
"password": "test",
"email": "email#gmail.com"
}
I have function like
-(NSString*) sendPostOnUrl:(NSString*) url
withParameters:(NSDictionary*)params{
__block NSString* response = nil;
NSError *error;
NSURL *u = [NSURL URLWithString:url];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL: u];
[httpClient postPath:REGISTER
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
return response;
}
where params are NSDictionary with keys username, password and email and values for those keys.
Problem is when I send I always in return get null in response (the latest line) but in NSLog I get json response.. I am very new to ios, and it looks to me that I need to sync on some way block with return from function but don't know how, can anybody give me a clue what am I doing wrong ? (params contains all those keys when I try to debug, url is ok, REGISTER is NSString constant)
Blocks are asynchronous - the problem here is that "response = [[NSString alloc] initWithData..." is within the block which gets executed after you've exited the method. A better approach is to not do this in a method, instead place this code where you were calling sendPostOnUrl:withParameters: and do whatever it is you need to do within the success block. So instead of:
self.something = [self sendPostOnUrl:url withParameters:#{"username":"test" etc}];
you do this:
NSError *error;
NSURL *u = [NSURL URLWithString:url];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL: u];
__weak YourClassName *me = self;
[httpClient postPath:REGISTER
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
me.something = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
Also, take note of "__weak YourClassName *me = self", you cannot reference self within a block because it will cause a retain cycle.

AFNetworking and 404

I am trying to post to a URL using AFNetworking and no matter what I do I keep getting the error:
Error Code: -1011 - Expected status code in (200-299), got 404
My code is as follows:
NSString *baseurl = #"http://mysiteurl";
NSString *path = #"/user/register/";
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseurl]];
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];
//[client setAuthorizationHeaderWithUsername:#"myusername" password:#"mypassword"];
[client postPath:path parameters:[NSDictionary dictionaryWithObjectsAndKeys:_userName,#"user", _email, #"email",_password,#"password", nil] success:^(AFHTTPRequestOperation *operation, id JSON) {
//NSLog(#"sjson: %#", [JSON valueForKeyPath:#"entries"]);
NSLog(#"sjson: %#", JSON);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error Code: %i - %#",[error code], [error localizedDescription]);
}];
When I go to http://mysiteurl/user/register/ directly I am able to see JSON.
What am I doing wrong?
When I go to http://mysiteurl/user/register/ directly I am able to see JSON.
If you're doing this through a browser, you are making a GET request, whereas in your code, you are making a POST request.
A 404 is not just the visible address, it includes the HTTP method as well. You need to make sure that your server responds to a POST at http://mysiteurl/user/register/. Depending on your framework (e.g. Rails), you may have to add [client setDefaultHeader:#"Accept" value:#"text/json"] to get the correct route.
i usually use [client getPath: parameters:params success:] not Post but i guess this will work for both cases since your response is in a JSON format too
add these two lines
[client.parameterEncoding = AFJSONParameterEncoding;
[client setDefaultHeader:#"Accept" value:#"text/json"];
before
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];

Resources