I keep receiving the following error message: 2013-01-22 01:44:43.091 Section3App2[16625:6703] -[__NSCFArray length]: unrecognized selector sent to instance 0x23a48780 after submitting my AFNetworking Request. The idea behind the request is that we are sending a post request to a REST API with a JSON Request Body via POST. I have been fiddling with this all day and can't seem to figure out whats causing the problem.
CODE
NSString *string = #"[{\"code\": \"105N14560\"}]";
NSString * jsonString = string;
NSData * data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError * error = nil;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
[request setHTTPBody:json];
// [request setValue:[NSString stringWithFormat:#"%d", string.length] forHTTPHeaderField:#"Content-Length"];
NSLog(#"request body:%#", request.HTTPBody);
// NSLog(#"json: %#",json);
// if (!json) {
// // handle error
// NSLog(#"fail");
// }
AFJSONRequestOperation *operation2 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"JSON: %#", JSON);
} failure:nil];
[operation2 start];
That code successfully creates the request body but when it tries to run the block it throws the error and I'm completely stumped. All help would be greatly appreciated.
Never try to build the JSON string yourself like you're doing in the first line. Use NSJSONSerialization to convert from a JSON-compatible Obj-C data structure (like NSDictionary or NSArray) directly to an NSData object to use as the body of the request. For example:
NSDictionary *JSON = [NSDictionary dictionaryWithObject:#"105N14560" forKey:#"code"];
id JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:error];
You should use the resulting JSONData object for both the HTTPBody of the request as well as the content-length of the request. Here is a complete example:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; // URL = wherever the request should be sent to
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"content-type"];
id JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:error];
if (JSONData) {
[request setValue:[NSString stringWithFormat:#"%d",[(NSData *)JSONData length]] forHTTPHeaderField:#"content-length"];
[request setHTTPBody:JSONData];
}
This just creates the request. The rest of it is straightforward using AFNetworking, where using AFJSONRequestOperation you just pass in the request as you've already done.
Related
I have to pass Authorization token in NSMutableURLRequest , My query is Whenever I have to pass Correct token than I am getting good response with https Status (200.. etc). but whenever I have to pass wrong Authorization token Than I am getting following response insted of http status code 401
* with wrong token response * (I had hide my query htpp:....)
Error Domain=NSURLErrorDomain Code=-1012 "(null)" UserInfo={NSErrorFailingURLStringKey=http......, NSUnderlyingError=0x60800024c420 {Error Domain=kCFErrorDomainCFNetwork Code=-1012 "(null)" UserInfo={_kCFURLErrorAuthFailedResponseKey={url = http.....}}}, NSErrorFailingURLKey=http....}
** here is my code **
// parameter in dictionary
NSDictionary *parameters = #{ #"user_id": [NSNumber numberWithInt:1]};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters
options:NSJSONWritingPrettyPrinted
error:&error];
// Convert dictionary to Json String
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
jsonparameter = jsonString;
}
NSData *postData = [jsonparameter dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:SiteAPIURL,wsname]]];
NSString *Accesstoken = [NSString stringWithFormat:#"Bearer %#",tokenInfo.access_token];
// Set Access token
[request setValue:Accesstoken forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSHTTPURLResponse __autoreleasing *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"%#",error.localizedDescription);
NSLog(#"Status code =%ld",(long)response.statusCode);
401 is server generated error. -1012 is system generated error. This sometimes may be because of app is keeping cached certificates and certificate on the server has been changed so they don't match. Clearing Caches and Preferences folders from app's home directory will delete the old certificate data and app will have to download the new one from the server and you problem will be solved.
I am trying to send a http url request of method type 'PATCH' below is my sample code .
NSString *urlString=#"http://0.0.0.0:8000/v1/APvk";
para=[para stringByAppendingFormat:#"/%#?accessToken=",#"SOMEID"];
para= [para stringByAppendingString:#"SOMEACCESSTOKEN"];
NSURL *url = [NSURL URLWithString:para];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
if (!request) NSLog(#"Error creating the URL Request");
[request setHTTPMethod:#"PATCH"];
[request setHTTPBody:data];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// Send a synchronous request
NSURLResponse * response = nil;
NSError * NSURLRequestError = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&NSURLRequestError];
NSLog(#"%#",responseData);
NSDictionary *Replyfromserver=[NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSLog(#"%#",Replyfromserver);
I don't know how to send a PATCH request I am just doing the same way we send a POST request ,here I am getting a message from server that is "Invalid Payload" Help me out of this.
I'm trying to access the following URL:
http://appointmentreminder4.azurewebsites.net/Profile
This URL uses a "Get" method, and is supposed to provide JSON results. Before accessing the URL, you need to login using your Email Address and Password. After logging in successfully, the Web API issues a token. This token is used in ALL communications going forward.
I am currently unable to retrieve the token in Objective-C. I have attempted to google this problem, but I cannot figure out:
1) How to get the token
2) How to get the JSON output from the URL.
Here is the code I have written so far that returns neither the JSON, nor the token:
NSDictionary *postDict = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Email Adress", #"MyEmailAddress",
#"Password", #"MyPassword",
nil];
NSError *error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:postDict options:kNilOptions error:&error];
NSURLResponse *response;
NSData *localData = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://appointmentreminder4.azurewebsites.net/home"]];
[request setHTTPMethod:#"POST"];
if (error == nil)
{
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPBody:jsonData];
// Send the request and get the response
localData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *result = [[NSString alloc] initWithData:localData encoding:NSASCIIStringEncoding];
NSLog(#"Post result : %#", result);
}
If the above link fails, use this link to navigate to the specific page:
http://appointmentreminder4.azurewebsites.net/home
trying get Data from server using #"GET" request,
this following code returns null all time:
is anybody finding an issue with my following code?
or it's can be server side Issue..
?
thank for your help!
+ (id)sendParam:(NSString*)ParamString url:(NSString*)url{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
NSString *post = ParamString;
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d",[postData length]];
[request setURL:[NSURL URLWithString:url]];
NSLog(#"postLength =%#",postLength);
[request setHTTPBody:postData];
[request setHTTPMethod:#"GET"];
[request addValue:ParamString forHTTPHeaderField:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLResponse *response;
NSError *error;
NSData *aData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSMutableArray*jsonReturn = [[NSMutableArray alloc]init];
jsonReturn = (NSMutableArray*)[NSJSONSerialization JSONObjectWithData:aData options:kNilOptions error:&error];
NSLog(#"jsonReturn %#",jsonReturn);
return jsonReturn;
}
after Editing:
+ (id)sendParam:(NSString*)ParamString url:(NSString*)url{
NSString*StringGETMETHOD = [NSString stringWithFormat:#"%#%#",url,ParamString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:[NSURL URLWithString:StringGETMETHOD]];
[request setHTTPMethod:#"POST"];
NSURLResponse *response;
NSError *error;
NSData *aData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"aData=%#",aData);
if (aData) {
jsonReturn=(NSMutableArray*)[NSJSONSerialization JSONObjectWithData:aData options:kNilOptions error:&error];
NSLog(#"jsonReturn %#",jsonReturn);
}
If you want to use GET for getting response from server just you can try in following method
//just give your URL instead of my URL
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://api.worldweatheronline.com/free/v1/search.ashx?query=London&num_of_results=3&format=json&key=xkq544hkar4m69qujdgujn7w"]];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"content-type"];
NSError *err;
NSURLResponse *response;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
//You need to check response.Once you get the response copy that and paste in ONLINE JSON VIEWER.If you do this clearly you can get the correct results.
//After that it depends upon the json format whether it is DICTIONARY or ARRAY
NSDictionary *jsonArray = [NSJSONSerialization JSONObjectWithData:responseData options: NSJSONReadingMutableContainers error: &err];
NSArray *array=[[jsonArray objectForKey:#"search_api"]objectForKey:#"result"];
I very much doubt that you should send this parameter as a HEADER field.
I also would think that you should be sending a POST and not a GET.
Setting jsonReturn to [[NSMutableArray alloc] init] is nonsense. Explain to yourself why you are doing it instead of setting jsonReturn to nil
Logging the jsonReturn is nonsense, because all the interesting stuff has disappeared. You should log the response and the data that was returned, at least if jsonReturn = nil.
You seem to be confused between GET and POST. You are doing a GET, but supplying data like a POST (usually does, though it isn't mandated, or precluded to use the body data for a GET).
Generally, you don't want to use body data for a GET, it isn't usual / expected so any number of different issues could be occurring. Either change setHTTPMethod: to #"POST" so you are doing a POST properly, or change the parameters to be part of the request URL.
It really all depends what the server expects (and can handle). This is what you need to know and match against...
Subsequently you have a different issue. The param string you supply has characters in it that need to be encoded (like spaces). Use stringByAddingPercentEscapesUsingEncoding: on the param string before you send it to escape these characters.
It works in a browser because it is adding the escape characters for you (which you should see in the browser address bar after it has loaded the response).
i found my issue:
sending paramString Using "Get" Method, cannot send parameters with space between letters.. example: "tel aviv" should be "tel%20aviv"
by adding the following code line:
**urlParam = [urlParam
stringByReplacingOccurrencesOfString:#" " withString:#"%20"];**
fix code:
+ (id)sendParam:(NSString*)ParamString url:(NSString*)url{
NSString* urlParam = [NSString stringWithFormat:#"%#%#",url,ParamString];
urlParam = [urlParam
stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlParam]];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"content-type"];
NSURLResponse *response;
NSError *error;
NSData *aData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"aData=%#",aData);
if (aData) {
jsonReturn=(NSMutableArray*)[NSJSONSerialization JSONObjectWithData:aData options:kNilOptions error:&error];
NSLog(#"jsonReturn %#",jsonReturn);
}
thank you all !
I'm working on a method to centralize my URL connections for sending and receiving JSON data from a server. It works with POST, but not GET. I'm using a Google App Engine server and on my computer it'll handle the POST requests and return proper results (and log appropriately), but I get the following error when I try the request with a GET method:
Error Domain=kCFErrorDomainCFNetwork Code=303 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)" UserInfo=0xd57e400 {NSErrorFailingURLKey=http://localhost:8080/api/login, NSErrorFailingURLStringKey=http://localhost:8080/api/login}
In addition, the GAE dev server shows a "broken pipe" error, indicating that the client closed the connection before the server was finished sending all data.
Here's the method:
/* Connects to a given URL and sends JSON data via HTTP request and returns the result of the request as a dict */
- (id) sendRequestToModule:(NSString*) module ofType:(NSString*) type function:(NSString*) func params:(NSDictionary*) params {
NSString *str_params = [NSDictionary dictionaryWithObjectsAndKeys:func, #"function", params, #"params", nil];
NSString *str_url = [NSString stringWithFormat:#"%#%#", lds_url, module];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:str_url]];
NSData *data = [[NSString stringWithFormat:#"action=%#", [str_params JSONString]] dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:type];
[request setHTTPBody:data];
[request setValue:[NSString stringWithFormat:#"%d", [data length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Error: %#", error);
NSLog(#"Result: %#", [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]);
return [result objectFromJSONData];
}
A sample call would be:
NSDictionary *response = [fetcher sendRequestToModule:#"login" ofType:#"GET" function:#"validate_email" params:dict];
Again, this works with a POST but not a GET. How can I fix this?
In my case i was not calling [request setHTTPMethod: #"POST" ]
I think the root cause is you have an invalid URL.
JSON encoding will include things like '{', '}', '[' and ']'. All of these need to be URL encoded before being added to a URL.
NSString *query = [NSString stringWithFormat:#"?action=%#", [str_params JSONString]];
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", str_url, query]];
To directly answer your question:
According to CFNetwork Error Codes Reference the error is kCFErrorHTTPParseFailure. This means the client failed to correctly parse the HTTP response.
The reason why is that a GET doesn't include a body. Why would you want to submit JSON in a GET anyways?
If the target api returns data only you pass it in the url params.
If you want to send data and "get" a response use a post and examine the body on return.
Sample Post:
NSError *error;
NSString *urlString = [[NSString alloc] initWithFormat:#"http://%#:%#/XXXX/MVC Controller Method/%#",self.ServerName, self.Port, sessionId ];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
// hydrate the remote object
NSString *returnString = [rdc JSONRepresentation];
NSData *s10 = [returnString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:s10];
NSURLResponse *theResponse = [[NSURLResponse alloc] init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&error];
NSString *message = [[NSString alloc] initWithFormat: #"nothing"];
if (error) {
message = [[NSString alloc] initWithFormat:#"Error: %#", error];
} else {
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
NSLog(#"%#", message);
return message;