Sending a NSMutableURLRequest request with "Body Requests" - ios

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];

Related

How to send base64 string through NSUrlSession IOS

As I'm converting images to base64 string and uploading it to serer using NSURLSessionsDataTask for example-
NSString *encodedString = [[self encodeToBase64String:imgParcel]stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
[self.package.arrParcelImages addObject:encodedString]
and sending it like this...
NSDictionary *postParameters = #{#"userID":#"1",#"images":self.package.arrParcelImages}
NSData *postData = [NSJSONSerialization dataWithJSONObject:postParameters options:NSJSONWritingPrettyPrinted error:&error];
NSString *dataString = = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"image/png" forHTTPHeaderField:#"Content-Type"];
NSString *strValue = [NSString stringWithFormat:#"%#",[USER_DEFAULTS objectForKey:UD_X_API_VALUE]];
if (strValue != nil) {
[request addValue:strValue forHTTPHeaderField:[USER_DEFAULTS objectForKey:UD_X_API_KEY]];
}
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *taskData, NSURLResponse *taskResponse, NSError *taskError) {
//NSLog(#"Start - Response:%# %#\n", taskResponse, taskError);
dispatch_async(dispatch_get_main_queue(), ^{
if (taskError) {
NSLog(#" Error = %#",[taskError localizedDescription]);
completionBlock(nil,taskError,task);
}
else {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:taskData options:kNilOptions error:&error];
if (json) {
NSLog(#" JSON = %#",json);
}
else {
NSString* newStr = [[NSString alloc] initWithData:taskData encoding:NSUTF8StringEncoding];
NSLog(#"Error: %#",newStr);
}
completionBlock(json,nil,task);
}
});
}];
[postDataTask resume];
But This is not uploading base64 string to server what i'm doing wrong please help
If you're including the base64 image in JSON, you should not percent escape the + characters. You only do that if you are creating x-www-form-urlencoded requests.
So, do not replace the + characters with %2B.
You are setting the Content-Type header twice. Your request is JSON, so remove the image/png header. Some web services will just blithely assume the content type, but perhaps yours is getting confused by the incorrect Content-Type header.
If it's still not working, the problem could either be how you created the base64 rendition of the image or the request is not formatted correctly. It's hard to know without seeing (a) what the final request looked like; and (b) precisely what the server is looking for.

Not able to send json string as param in post request in iOS?

I am trying to send the Json string as param in post request but i am not able to do that. I have an array of phone numbers from that i am generating a json string follwing is the code for that
int i=0;
NSMutableArray *contacts = [[NSMutableArray alloc] init];
for (i=0; i<[all_contacts count]; i++)
{
[contacts addObject:#{#"phone" : [all_contacts objectAtIndex:i]}];
}
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:contacts options:0 error:&error];
if (!jsonData)
{
//error here
}
else
{
JsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"json string is %#",JsonString);
}
Now i am converting into nsdata to send to server using post request but i am not able to do that.
//append base url with main url
NSString* urlString=[BASE_URL stringByAppendingString:ADD_CONTACTS];
// the server url to which the image (or the media) is uploaded. Use your server url here
NSURL* requestURL = [NSURL URLWithString:urlString];
// Create the request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
// Specify that it will be a POST request
request.HTTPMethod = #"POST";
// This is how we set header fields
[request setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:api_key forHTTPHeaderField:#"Authorization"];
// Convert your data and set your request's HTTPBody property
NSDictionary *_params = [NSDictionary dictionaryWithObjectsAndKeys:
JsonString, #"contacts",
nil];
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:_params options:0 error:nil];
request.HTTPBody = jsonData;
NSString *string = [NSString stringWithUTF8String:[jsonData bytes]];
NSLog(#"ns local data is%#", string);
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
You seem to overthink it a bit. You have an array of dictionaries in contacts. Why not simply do the following?
NSError *error = nil;
NSDictionary *_params = #{#"contacts": contacts};
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:_params options:0 error:&error];
request.HTTPBody = jsonData;

How to solve NSErrorFailingURLStringKey in iOS?

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.

How to include JSON in the form field using AFHTTPRequestOperation

I'm trying to use an AFHTTPRequestOperation (via an AFHTTPRequestOperationManager) to transmit some information (say, "foo = bar") to an backend expecting JSON, using a setup like this:
- (void) postTest {
NSString *completePath = #"https://httpbin.org/post";
NSDictionary *dataToJSONfy = #{#"foo":#"bar"};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: dataToJSONfy options:kNilOptions error:&error];
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:#"POST" URLString:completePath parameters:nil];
request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:jsonData];
AFHTTPRequestOperation *operation =
[self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id JSON) {
NSLog(#"... success! %#", JSON);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"... failure! Error: %#", error);
}];
[self.operationQueue addOperation:operation];
}
Which shows up like this
{
args = {
};
data = "{\"foo\":\"bar\"}";
files = {
};
form = {
};
headers = {
[...]
};
json = {
foo = bar;
};
origin = [...];
url = "http://httpbin.org/post";
}
Question: what would I need to change in order to include my information ("foo = bar;") in the 'form =' section of the body rather than the 'json =' bit?
I want to include valid JSON (e.g. some server response stored earlier) in the post, but as per API specification, everything's supposed to be located under the 'form = {};' part. So I guess I want JSON as formdata.
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: dataToJSONfy options:kNilOptions error:&error];
//new!
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *bodyString = [NSString stringWithFormat:#"{'Form': '%#'}, jsonString]; //! not 100% what you want. I stick with valid JSON here
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:#"POST" URLString:completePath parameters:nil];
request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:bodyData]; //!
first you need to declare nsdictionary block just after the postTest method like
__block NSDictionary *dict=[NSDictionary alloc] init];
and in success block you should use
dict=[NSJSONSerlization JSONObjectWithData:JSON options:NSJSONReadingAllowFragments error:nil];
NSLog(#"... success! %#", dict);

Difference between Post & Get method in Json Parsing in ios

I implement the JSON Parsing as follow:
-(void)getallEvent
{
SBJSON *json = [SBJSON new];
json.humanReadable = YES;
responseData = [[NSMutableData data] retain];
NSString *service = #"/GetAllVenue";
NSString *str;
str = #"Calagary";
NSString *requestString = [NSString stringWithFormat:#"{\"CityName\":\"%#\"}",str];
//NSLog(#"request string:%#",requestString);
// NSString *requestString = [NSString stringWithFormat:#"{\"GetAllEventsDetails\":\"%#\"}",service];
NSData *requestData = [NSData dataWithBytes: [requestString UTF8String] length: [requestString length]];
NSString *fileLoc = [[NSBundle mainBundle] pathForResource:#"URLName" ofType:#"plist"];
NSDictionary *fileContents = [[NSDictionary alloc] initWithContentsOfFile:fileLoc];
NSString *urlLoc = [fileContents objectForKey:#"URL"];
urlLoc = [urlLoc stringByAppendingString:service];
//NSLog(#"URL : %#",urlLoc);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: urlLoc]];
NSString *postLength = [NSString stringWithFormat:#"%d", [requestData length]];
[request setHTTPMethod: #"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: requestData];
// self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
NSError *respError = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &respError ];
if (respError)
{
NSString *msg = [NSString stringWithFormat:#"Connection failed! Error - %# %#",
[respError localizedDescription],
[[respError userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Check your network connection" message:msg delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
else
{
NSString *responseString = [[NSString alloc] initWithData:returnData encoding: NSUTF8StringEncoding];
NSDictionary *results = [[responseString JSONValue] retain];
//NSLog(#" %#",results);
NSString *extractUsers = [[results objectForKey:#"d"] retain];
NSDictionary *finalResult = [[extractUsers JSONValue] retain];
NSLog(#"Final Results : %#",finalResult);
listOfEvents = [finalResult objectForKey:#"List of Event details of given Venue"];
}
Using this code, it slow down the app. How can I parse the json in background?
*Is this right for Post Method? what is the difference between Post & Get Method?*
Is there any other way to json parsing?
You are using synchronous request which is executed on Main thread so if you need to do it in background use asynchronous loading.
POST METHOD:
The POST method generates a FORM collection, which is sent as a HTTP request body. All the values typed in the form will be stored in the FORM collection.
GET METHOD: The GET method sends information by appending it to the URL (with a question mark) and stored as A Querystring collection. The Querystring collection is passed to the server as name/value pair. The length of the URL should be less than 255 characters.
An HTTP GET is a request from the client to the server, asking for a resource.
An HTTP POST is an upload of data (form information, image data, whatever) from the client to the server.
Check this answer for more details : what-is-the-difference-between-post-and-get
You are making synchronous communication request which slows down the application. You should make the asynchronous request to keep your app responsive.
It is not having any concern with parsing JSON data.
I would recommend using AFNetworking in your context which will simplify the connection management, background queue execution and parsing of the JSON you are getting back form the server.
The code example below will create an HTTP client with a base URL (<hostname>) and get a JSON payload from a given path. The network request runs in the background and runs a given block when completing
httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
// set the type to JSON
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
[httpClient setParameterEncoding:AFJSONParameterEncoding];
// Activate newtork indicator
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
// Request the <path> from the server and parse the response to JSON
// this calls a GET method to <hostname>/<path>
[httpClient getPath:<your path> parameters:Nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
// responseObject is a JSON object here
//
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// handle error
}];
Get: With the get method the value is send through the query string appended with the url. So you can see the the name, value, description on the addressbar when the page display in the browser.
Post: This method transfer the information through the complete form. You can not see the detail description on the addresss bar. When the page display.
NSString *myUrlString =[NSString stringWithFormat: #"your url];
NSString *postdata=[NSString stringWithFormat:#"emailId=%#&password=%#,username,password];
NSLog(#"%#",postdata);
//create a NSURL object from the string data
NSURL *myUrl = [NSURL URLWithString:myUrlString];
//create a mutable HTTP request
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:myUrl];
//sets the receiver’s timeout interval, in seconds
[urlRequest setTimeoutInterval:30.0f];
//sets the receiver’s HTTP request method
[urlRequest setHTTPMethod:#"POST"];
//sets the request body of the receiver to the specified data.
[urlRequest setHTTPBody:[postdata dataUsingEncoding:NSUTF8StringEncoding]];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//Loads the data for a URL request and executes a handler block on an
//operation queue when the request completes or fails.
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 && error == nil){
//process the JSON response
//use the main queue so that we can interact with the screen
dispatch_sync(dispatch_get_main_queue(), ^{
[self parseResponse:data];
});
}
else if ([data length] == 0 && error == nil){
NSLog(#"Empty Response, not sure why?");
}
else if (error != nil){
NSLog(#"Not again, what is the error = %#", error);
}
}];
}
- (void) parseResponse:(NSData *) data
{
responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"JSON = %#", responseData);
NSLog(#"Response ==> %#", responseData;
Finally u get the response from that specific url .and what ever u wanted to it do ur own way.

Resources