I am new to iOS. I am developing an application which retrieves data from a server using the HTTP POST method.
I pass an NSDictionary as POST parameters with my URL.
NSDictionary format is like this:
{
"draw_id" = 6;
"block_numers" = {
"block_number" = 1;
"draw_day" = Both;
"number_1" = 1;
"number_2" = 3;
"number_3" = 20;
"number_4" = 25;
"number_5" = 40;
"star_1" = 2;
"star_2" = 6;
};
"game_id" = 1;
"user_id" = 51;
}
And my url is http://xxx.xxx.xx.xx:3000/xxxxxxx_protocol_xxx
I used following function to retrieve data from server.
-(NSDictionary*)getJsonDataFromPostURl:(NSString *)postUrl JsonParserType:(NSString *)type PostData:(NSDictionary *)postData{
NSData *jsonData = [self jsonTrackDataForUploadingToCloud:postData]; // Method shown below.
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
//NSLog(#"Json String: %# URL: %#", jsonString,postUrl); // To verify the jsonString.
NSLog(#"GetJsonDataFromPostUrl: JsonString: %#",jsonString);
NSURL *url=[NSURL URLWithString:postUrl];
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
[postRequest setHTTPMethod:type];
[postRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[postRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[postRequest setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[jsonData length]] forHTTPHeaderField:#"Content-Length"];
[postRequest setHTTPBody:jsonData];
NSURLResponse *response = nil;
NSError *requestError = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&requestError];
if (requestError == nil) {
NSString *returnString = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[returnString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
if([result isKindOfClass:[NSDictionary class]]){
return result;
}
} else {
NSLog(#"NSURLConnection sendSynchronousRequest error: %#", requestError);
}
return nil;
}
this function is working correctly with other Parameters and other api but is return following error with this API:
Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo=0x7a228e10 {NSErrorFailingURLStringKey=payment_protocol_api, NSErrorFailingURLKey=payment_protocol_api, NSLocalizedDescription=unsupported URL, NSUnderlyingError=0x7a701f50 "unsupported URL"}
Please help me out. Thank you in advance.
Related
In my project i am passing this API: http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat with params: prod_id=25,var_id=140.
The problem is when i am pass this api in Rest Client it displays correct response but when i am trying to put it in my code it shows different response.
i am using the following code:
-(void)listofNotice
{
NSString *post = [NSString stringWithFormat:#"prod_id=25,var_id=140"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
//NSString *str=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
//NSLog(#"str : %#",str);
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
}
- (id)cleanJsonToObject:(id)data
{
NSError* error;
if (data == (id)[NSNull null])
{
return [[NSObject alloc] init];
}
id jsonObject;
if ([data isKindOfClass:[NSData class]])
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
}
else
{
jsonObject = data;
}
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSMutableArray *array = [jsonObject mutableCopy];
for (int i = (int)array.count-1; i >= 0; i--)
{
id a = array[i];
if (a == (id)[NSNull null])
{
[array removeObjectAtIndex:i];
} else
{
array[i] = [self cleanJsonToObject:a];
}
}
return array;
}
else if ([jsonObject isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictionary = [jsonObject mutableCopy];
for(NSString *key in [dictionary allKeys])
{
id d = dictionary[key];
if (d == (id)[NSNull null])
{
dictionary[key] = #"";
} else
{
dictionary[key] = [self cleanJsonToObject:d];
}
}
return dictionary;
}
else
{
return jsonObject;
}
}
it display the following response:
str : {
business = 0;
"business-list" = "Business list empty.";
response = 401;
}
but the actual response is something like this
please help me.. Thanks In advance
Please change this
NSString *post = [NSString stringWithFormat:#"prod_id=25,var_id=140"];
To:
NSString * post =[NSString stringWithFormat:#"prod_id=25&var_id=140"];
if possible use this:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.HTTPAdditionalHeaders = #{#"application/x-www-form-urlencoded" : #"Content-Type"};
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:#"http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *requestData = [post dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:requestData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data != nil){
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger code = [httpResponse statusCode];
NSLog(#"Status Code: %ld", (long)code);
if (code == 200) {
NSError *error;
id responseObject =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
}
}
}];
[postDataTask resume];
OR
NSString *postString = [NSString stringWithFormat:#"prod_id=%#&var_id=%#",#"25",#"140"];
NSURL *urlPath = [NSURL URLWithString:#"http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlPath
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
NSData *requestData = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:requestData];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[APP_DELEGATE removeLoader];
if(data != nil) {
NSDictionary *responseObject =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSLog(#" %#", responseObject);
}
else {
}
}];
Hope this helps.
I think you need to change below code
NSString *post = [NSString stringWithFormat:#"prod_id=25,var_id=140"];
to
NSDictionary *prodDict=#{#"prod_id":#"25",
#"var_id":#"140"};
I'm currently working with YouTube API and allowing users to subscribe to other channels, however now I'm supposed to send a POST method that includes a "Request Body".
Here's the Request that's I'm supposed to send :
POST https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&key={YOUR_API_KEY}
//The Request Body
{
"snippet": {
"resourceId": {
"channelId": "UCJZ7f6NQzGKZnFXzFW9y9UQ"
}
}
}
Here's my current code
+(void)subscribeToChannel:(NSString *)channelID {
GTMOAuth2Authentication *auth;
auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName clientID:clientIDclientSecret:clientSecret];
NSString *urlStr;
NSMutableURLRequest *request;
urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/subscriptions?id=%#&key=mykey", channelID];
[request setHTTPBody:[#"{ \"snippet\": { \"resourceId\": { \"channelId\": \"UCJZ7f6NQzGKZnFXzFW9y9UQ\" } } }" dataUsingEncoding:NSUTF8StringEncoding]];
NSURL *url = [NSURL URLWithString:urlStr];
request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[auth authorizeRequest:request
completionHandler:^(NSError *error) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
NSString *output = nil;
if (error) {
output = [error description];
NSLog(#"ERRO LOADING INFO : %#", output);
} else {
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:nil];
if (data) {
output = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
} else {
output = [error description];
}
}
});
}];
}
I'm positive that I'm doing something wrong in [request setHTTPBody] but that's the only thing that I could think about.
You're attempting to set the NSMutableURLRequest's HTTPBody before you have allocated an instance of NSMutableURLRequest.
NSString *urlStr;
// The request is nil
NSMutableURLRequest *request;
urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/subscriptions?id=%#&key=mykey", channelID];
// At this point the request is still nil so you are attempting to set the HTTPBody on a nil object
[request setHTTPBody:[#"{ \"snippet\": { \"resourceId\": { \"channelId\": \"UCJZ7f6NQzGKZnFXzFW9y9UQ\" } } }" dataUsingEncoding:NSUTF8StringEncoding]]
You also mentioned in a comment that you are receiving a "This API does not support parsing form-encoded input." error. You may be receiving this error because you are not setting the content-type (I came to this conclusion from googling the error. I may be wrong).
This should work:
NSString * urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/subscriptions?id=%#&key=mykey", channelID];
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
// Set the content type
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// Create the dictionary that you will be using in the HTTPBody
NSDictionary * httpBody = #{
#"snippet": #{
#"resourceId": #{
#"channelId": channelID
}
}
};
// Make sure that the above dictionary can be converted to JSON data
if([NSJSONSerialization isValidJSONObject:httpBody])
{
// Convert the JSON object to NSData
NSData * httpBodyData = [NSJSONSerialization dataWithJSONObject:httpBody options:0 error:nil];
// set the http body
[request setHTTPBody:httpBodyData];
}
I do this when bumping places using the Google Places API, but it should work the same.
Try this:-
NSMutableDictionary *channelId = [[NSMutableDictionary alloc]init];
[channelId setObject:#"UCJZ7f6NQzGKZnFXzFW9y9UQ" forKey:#"channelId"];
NSMutableDictionary *resourceId = [[NSMutableDictionary alloc]init];
[resourceId setObject:channelId forKey:#"resourceId"];
NSDictionary * postDictionary = [NSDictionary dictionaryWithObject:resourceId forKey:#"snippet"];
NSError * error = nil;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:postDictionary options:NSJSONWritingPrettyPrinted error:&error];
[request setHTTPBody:jsonData];
I have a simple app which makes a POST request. And then data is returned. The problem is that the returned data is not JSON..... So how can I view it? Here is my code:
NSString *requestString = [NSString stringWithFormat:#"https://serveraddress.com"];
NSString *string = [NSString stringWithFormat:#"id=%#&olt_info=%#", #"test", #"renz"];
NSData *postData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestString]];
NSLog(#"\n request str : %#",request);
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"The responce:\n\n%#", responseData);
if (error == nil && response.statusCode == 200) {
NSLog(#"%li", (long)response.statusCode);
NSError *err;
id JSon = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&err];
if (err) {
NSLog(#"%#",err);
}
else {
NSLog(#"Json %#",JSon);
}
}
else {
//Error handling
NSLog(#"%#", response);
}
This is the format of the returned data that I am trying to read:
new_token=509723045780uIRBWRBH24b
So I know the downloaded data gets stored in the NSData called "responseData". But if I print it using NSLog I just get this:
<61636365 73735f74 6f6b656e 3d313538 32353838 33343337 39343431 7c365f4d 6543436e 6b51716f 722d6e70 61746662 484d6458 526b3477>
So how do I read this???
Thank you for your time, Dan.
To get NSString from NSData use
NSString *decodedString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
maybe this string will have a valid JSON format.
NSString *requestString = [NSString stringWithFormat:#"https://serveraddress.com"];
NSString *string = [NSString stringWithFormat:#"id=%#&olt_info=%#", #"test", #"renz"];
NSData *postData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestString]];
NSLog(#"\n request str : %#",request);
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
*id json = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];*
NSLog(#"%#", json);
if (error == nil && response.statusCode == 200) {
NSLog(#"%li", (long)response.statusCode);
NSError *err;
id JSon = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&err];
if (err) {
NSLog(#"%#",err);
}
else {
NSLog(#"Json %#",JSon);
}
}
else {
//Error handling
NSLog(#"%#", response);
}
Posted a query previously about JSON parsing not working properly. Did more looking into it with a packet sniffer and also with another client that works properly and found out it's a syntax thing, that I still can't seem to solve.
The code in the bottom makes the HTTP request to have the JSON in it as:
{"key":"value"}
And my server is actually looking for a JSON in the following syntax:
key=%22value%22
I tried to write some code that does this manually, but figured there must be something out of the box for iOS, and I don't want to have faults in the future.
I messed around with it for a while trying to find the right code for the job, but couldn't (you can see some code I tried commented out). Can anyone help me?
+ (NSString*)makePostCall:(NSString*)urlSuffix
keys:(NSArray*)keys
objects:(NSArray*)objects{
NSDictionary *params = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
// NSString *dataString = [self getDataStringFromDictionary:params];
// NSData *jsonData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params
options:0
error:&error];
// id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
// NSLog(#"%#", jsonObject);
if (!jsonData) {
// should not happen
NSError *error;
NSLog(#"Got an error parsing the parameters: %#", error);
return nil;
} else {
// NSString *jsonRequest = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// NSLog(#"%#", jsonRequest);
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", urlPrefix, urlSuffix]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
// NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
// [request setValue:#"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: jsonData];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
// TODO: handle error somehow
NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return returnString;
}
}
This is my code for sending a post request to a nodejs backend.
CLLocation* location = [locationManager location];
CLLocationCoordinate2D coord = [location coordinate];
NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://50.63.172.74:8080/points"]];
//[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
NSDictionary* jsonDict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:coord.latitude], #"lat", [NSNumber numberWithFloat:coord.longitude], #"lng", nil];//dictionaryWithObjectsAndKeys:coord.latitude, nil]
NSString *postString;
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
postString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
(void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
Using express I'm getting the request.body back on the server but it looks like this:
{ '{\n "lat" : 0.0,\n "lng" : 0.0\n}': '' }
and I can't access it by just saying request.body.lat since it comes back as undefined.
I want the body to look like:
{ "lat":0.0, "lng":0.0}
Any idea on how to do that using express?
May this help you.
Please replace 0.0 with your actual coordiantes
NSArray *keys = [NSArray arrayWithObjects:#"lat", #"lng", nil];
NSArray *objects = [NSArray arrayWithObjects:#"0.0",#"0.0", nil];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSData *jsonData ;
NSString *jsonString;
if([NSJSONSerialization isValidJSONObject:jsonDictionary])
{
jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:0 error:nil];
jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
}
NSString *requestString = [NSString stringWithFormat:
#"http://50.63.172.74:8080/points"];
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody: jsonData];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [jsonData length]] forHTTPHeaderField:#"Content-Length"];
NSError *errorReturned = nil;
NSURLResponse *theResponse =[[NSURLResponse alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&errorReturned];
if (errorReturned) {
NSLog(#"Error %#",errorReturned.description);
}
else
{
NSError *jsonParsingError = nil;
NSMutableArray *arrDoctorInfo = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:&jsonParsingError];
NSLog(#"Dict %#",arrDoctorInfo);
}
The problem is that after you use NSJSONSerialization to obtain a NSData object containing your JSON data, you then create postString from that data. Eliminate that unnecessary step, and just do:
[request setHTTPBody:jsonData];
And you should get the expected JSON in your server-side code.