AFNetworking returning invalid response object - ios

I am considering using AFNetworking in one of my projects. But I have a problem.
Here is the code:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:completeUrlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", responseObject);
} failure:nil];
The problem Is the respose object. It is a dictionary with only a value inside. The value is shown to be a NSObject! That should actually be a NSDictionary with several key/value pairs.
Here is the raw json:
{
"signInResponse": {
"userName": "971777771554300",
"duration": 315360000000,
"token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"userId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"idleTimeout": 2592000000
}
}
Why does the parser fail? Also I would like to note that the url does not end in ".json" as it is dinamically created.
Another small question: several resposes return json objects where the keys that need to be in the
response dictionary are of the form "#importantKey" or "#key". I remmember that some parsers can't returns such keys in their response, is this a problem for AFNetworking?

if you use alamofire, this little snippet can help, maybe you need to do casting like this :
var innerData = data!["signInResponse"]!!
var innerData2 = innerData[0]
var DataDict = (innerData2 as! NSDictionary) as Dictionary
self.userName = DataDict["userName"]! as! String

Related

(POST Request) Parse JSON elements from a URL response in Objective-C

I am having trouble with parsing/returning JSON from a URL response. Here is an example
lets say I submit this to a server [POST not GET]
firstname=first&lastname=last&age=99
and the response from the server is this
{
"person":{
"firstname":"first",
"lastname":"last",
"info":{
"age":"99"
}
}
}
how would I retrieve this information (certain elements)
lets say I JUST want the persons age so the return string should be just "99"
or how do I JUST return the lastname or JUST the firstname, another thing how would I pass the returned element into the next POST request without the user having to type it again?
if anyone can find an example that would be fantastic :)
Thank You!
lets say the name of this data is json (you called it response). This is a dictionary. What this means is that it has key/value pairs. To access it do the following:
To get any of this information in the dictionary, all you need is a one line of code!!
To get detail of a person's first name,
[response valueForKeyPath:#"person.firstname"];
To get last name :
[response valueForKeyPath:#"person.lastname"];
To get age :
[response valueForKeyPath:#"person.info.age"];
Hmm... If it were me, I would just get the NSDictionary, then look inside the NSDictionary.
To get age:
You would want to get { "firstname":"first", "lastname":"last", "info":{ "age":"99" } }, so do:
[responseObject objectForKey:#"person"];
After you do that, you would want to get { "age":"99" }. To do that, you should use
[[responseObject objectForKey:#"person"]objectForKey:#"info"];
After that, 1 last step to get the value for age:
[[[responseObject objectForKey:#"person"]objectForKey:#"info"]objectForKey:#"age"];
And then, you have age.
To get firstname
Just find the object for key firstname by doing:
[[responseObject objectForKey:#"person"]objectForKey:#"firstname"];
To get lastname
[[responseObject objectForKey:#"person"]objectForKey:#"lastname"];
... The rest should follow the same rule.
How to pass it back to a POST request
Well, the POST request takes in an id parameters. This is where you would put the dictionary. To do this correctly without having to deal with any asynchrony, you would have to make the POST request inside the GET request. For example:
[manager GET:<your GET url>
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[manager POST:<your POST url>
parameters:responseObject
success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(#"Success!"); }
failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(#"Error: %#", error); }];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(#"Error: %#", error); }];
Well, that's pretty much it. Hope this helped :)

AFNetworking accept content type error: {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

I am using AFNetworking to GET a plain/text:
let manager = AFHTTPRequestOperationManager()
manager.GET(url, parameters: nil, success: { (op: AFHTTPRequestOperation!, res: AnyObject!) -> Void in
},failure: { (op: AFHTTPRequestOperation!, er:NSError!) -> Void in
println(op,er)
})
The accept content types:
manager.responseSerializer.acceptableContentTypes
[text/javascript, application/json, text/json]
So I got error in failure block:
NSLocalizedDescription=Request failed: unacceptable content-type: text/plain}
Then i added text/plain in this way:
var set = manager.responseSerializer.acceptableContentTypes
set.insert("text/plain")
manager.responseSerializer.acceptableContentTypes = set
right now the types are:
manager.responseSerializer.acceptableContentTypes
[application/json, text/javascript, text/plain, text/json]
But i got the new error:
{ URL: http://192.168.1.9:8081/sec.jsp } { status code: 200, headers {
"Content-Length" = 44;
"Content-Type" = "text/plain; charset=utf-8";
Expires = "Thu, 01 Jan 1970 00:00:00 GMT";
Server = "Jetty(6.1.10)";
"Set-Cookie" = "JSESSIONID=tapmhct7hanv;Path=/";
} }>, 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=0x7fda31fb4a90 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})
I think the question is because JSON can't read the response. But i have set it to text/plain, does it still try to parse the plain text as JSON?
I searched and try a way:
manager.responseSerializer = AFJSONResponseSerializer(readingOptions: NSJSONReadingOptions.AllowFragments)
But the error is:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Garbage at end.) UserInfo=0x7ff4b1790660 {NSDebugDescription=Garbage at end.})
Man, this is what I added in when I config my AFNetworking class and it works fine.
The reason you got that 3840 error, is because your API server returns an integer or even empty stuff, which ios json parser failed.
Can u make sure in swift, the phrase your are using is correct way?
_delegateClient.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFJSONResponseSerializer
serializerWithReadingOptions:NSJSONReadingAllowFragments];
[manager GET:url parameters:parameters progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(#"request: %#\n", responseObject);
completionBlock(responseObject,nil);
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(#"Error: %#\n", error);
completionBlock(nil,error);
}];

AFHTTPRequestOperationManager file upload returns 500 server error

Im trying to upload camera taken photo to webservice with afnetworking.
this my upload part code :
CGSize newSize = CGSizeMake(500.0f, 500.0f);
UIGraphicsBeginImageContext(newSize);
[_imagedata drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imgData = UIImageJPEGRepresentation(newImage, 0.9f);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"user": "test_user"};
[manager POST:#"http://www.mywebsite.com/webservice.aspx" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[formData appendPartWithFormData:imgData name:#"image"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Im using Asp.net as my webservice.
this is my server side code :
string USER = Server.UrlDecode(Request["user"]),
SqlParameter prmUser = sc.Parameters.Add("#user", SqlDbType.VarChar);
prmUser.Direction = ParameterDirection.Input;
prmUser.Value = USER;
HttpFileCollection MyFileCollection = Request.Files;
if (MyFileCollection != null && MyFileCollection.Count > 0 && MyFileCollection[0] != null)
{
SqlParameter prmImage = sc.Parameters.Add("#Image", SqlDbType.Image);
prmImage.Direction = ParameterDirection.Input;
byte[] buf = new byte[MyFileCollection[0].ContentLength];
MyFileCollection[0].InputStream.Read(buf, 0, MyFileCollection[0].ContentLength);
prmPhoto.Value = buf;
}
sc.ExecuteNonQuery();
now everytime i run program this error apears :
Error: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: internal server error (500)" UserInfo=0x1555ff60 {com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x16a94010> { URL: http://www.mywebsite.com/webservice.aspx } { status code: 500, headers {
Connection = close;
"Content-Length" = 3420;
"Content-Type" = "text/html; charset=utf-8";
Date = "Wed, 01 Apr 2015 15:56:21 GMT";
Server = "Microsoft-IIS/8.5";
Via = "1.1 magellan-front (squid/3.5.1)";
"X-AspNet-Version" = "4.0.30319";
"X-Cache" = "MISS from magellan-front";
"X-Powered-By" = "ASP.NET";
} }, NSErrorFailingURLKey=http://www.mywebsite.com/webservice.aspx, NSLocalizedDescription=Request failed: internal server error (500),
the detailed error :
[HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (image="...�5�Ƨ&�����<I
�(�ep��K�,�=mp�...").]
also the webservice works well with android HttpFileUpload method.
I was trying to find the basics of this, here is the link
What it seems from your code is that the client side seems to have a issue. Why don't you try using appendPartWithFileURL:name:fileName:mimeType:error:, and say if that doesn't work then the issue has to be from server side.
I don't know much about ASP.NET, but could you once verify your way how you are trying to read the file. Here is the link where in I found something interesting you might wanna try implementing.
The enumerator on the HttpFileCollection returns the keys (names) of the files, not the HttpPostedFileBase objects. Once you get the key, use the Item ([]) property with the key (filename) to get the HttpPostedFileBase object.
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
...
}
Let me know if this doesn't work.
Try uploading the image as a file (appendPartWithFileData) rather than as form data (appendPartWithFormData), and setting a content-type:
[formData appendPartWithFileData:imgData name:#"image"
fileName:#"image.jpg" mimeType:#"image/jpeg"];
Also see https://stackoverflow.com/a/15413152/1469259

(Cocoa error 3840.)" (Invalid value around character 0.) AFNetworking

I've been getting the following error when using the GET method to retrieve a file from a server:
Error: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x16e81ed0 {NSDebugDescription=Invalid value around character 0.}
I've tried a number of different things and I believe it could be something to do with the JSON format on the file that I'm trying to get.
Here is the code I've been using:
_username = #"JonDoe";
NSDictionary *parameters = #{ #"username" : _username};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/plain"];
[manager GET:#"http://.........."
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
My POST method works fine. I just can't seem to fix this issue with the GET. Any ideas? Thank you.
Judging by the discussion in the comments it appears that your GET request is successful (response code 200), but the response body is not valid JSON (nor a JSON fragment) as you have requested by your use of AFJSONResponseSerializer. A basic AFHTTPResponseSerializer can be used for responses that are not JSON.
I am pretty sure that you have a valid response from server but your response is not a valid format in JSON, probably because you have carachters in front of first { .
Please try this: Put the same URL address manually in your browser and you will see the culprit in the response. Hope it helped.
Hey guys this is what I found to be my issue: I was calling Alamofire via a function to Authenticate Users: I used the function "Login User" With the parameters that would be called from the "body"(email: String, password: String) That would be passed
my errr was exactly:
optional(alamofire.aferror.responseserializationfailed(alamofire.aferror.responseserializationfailurereason.jsonserializationfailed(error domain=nscocoaerrordomain code=3840 "invalid value around character 0." userinfo={nsdebugdescription=invalid value around character 0
character 0 is the key here: meaning the the call for the "email" was not matching the parameters: See the code below
func loginUser(email: String, password: String, completed: #escaping downloadComplete) {
let lowerCasedEmail = email.lowercased()
let header = [
"Content-Type" : "application/json; charset=utf-8"
]
let body: [String: Any] = [
"email": lowerCasedEmail,
"password": password
]
Alamofire.request(LOGIN_USER, method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in
if response.result.error == nil {
if let data = response.result.value as? Dictionary<String, AnyObject> {
if let email = data["user"] as? String {
self.userEmail = email
print(self.userEmail)
}
if let token = data["token"] as? String {
self.token_Key = token
print(self.token_Key)
}
"email" in function parameters must match the let "email" when parsing then it will work..I no longer got the error...And character 0 was the "email" in the "body" parameter for the Alamofire request:
Hope this helps

How to pass two parameters (NSString) and receive text-plain using Rest-Kit?

I have one service REST/JSON. It looks like:
#GET
#Produces(MediaType.TEXT_PLAIN)
#Path("/login/{userName}/{password}")
public synchronized String login(#PathParam("userName") String userName,
#PathParam("password") String password);
How do I consume this using RestKit in IOS?
It's obvious that in order to send canonical restkit requests you ought to have entities, mappings etc. Documentation provides explicit answer of how to do it.
I can also suggest you using the easy way:
[[RKObjectManager sharedManager].HTTPClient postPath:#"your URL string" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"WHOOO");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//
}];
responseObject is what you need.

Resources