NSMutableURLRequest POST method with multiple objects - ios

Below is my POST request example which saves Employee details. This work fine and I'm sending individual employee details.
But what if I have to save more then one Employee details...do I have to call below method those many time's ... How can I send all data in individual object like nsmutablearray of nsmutable dictionary....
-(void)saveEmployDetails
{
NSString * strBody = #"Employee=1&Class=tes&Comp=test&Type=Fixed";
NSString *strUrl = [[NSString alloc] initWithFormat:#"%#/api/external/SaveEmployee?type=%#", strCompURL, strType];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strUrl]];
request.HTTPMethod = #"POST";
request.HTTPBody = [strBody dataUsingEncoding:NSUTF8StringEncoding];
request.timeoutInterval = 5;
NSURLSessionDataTask *task = [sessionMnger dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:nil];
NSLog(#"data:%#", jsonData);
}
}
else
NSLog(#"Error:%#", error.description);
}];
[task resume];
}
Webservice Team gave me body for above API POST call like
This is a Post Method and below is the Body Object
[
{
"Employee":937,
"Class":test,
"Comp":test,
"Type":test
}
]
How to send more then one employee details together in above API

So the Webservice accepts json.
Just create an NSDictionary like this:
NSDictionary *emp = #{#"Employee":[NSNumber numberWithInt:1],
#"Class":#"Test",
#"Comp":#"Test",
#"Type":#"test"};
NSDictionary *emp1 = #{#"Employee":[NSNumber numberWithInt:1],
#"Class":#"Test2",
#"Comp":#"Test2",
#"Type":#"test2"};
NSArray *uploadArray = #[emp,emp1];
NSString *strUrl = [[NSString alloc] initWithFormat:#"%#/api/external/SaveEmployee?type=%#", strCompURL, strType];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strUrl]];
request.HTTPMethod = #"POST";
[request setHTTPBody:[NSJSONSerialization dataWithJSONObject:uploadArray options:NSJSONWritingPrettyPrinted error:nil]];
request.timeoutInterval = 5;
NSURLSessionDataTask *task = [sessionMnger dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:nil];
NSLog(#"data:%#", jsonData);
}
}
else
NSLog(#"Error:%#", error.description);
}];
[task resume];

Yes You can POST n number of employee details using your Web Service.

I think, you want to pass the NSArray inside the NSDictionary as a parameter along with the url to server.
Try like Hermann Klecker's answer and make changes accordingly:
[
{
"Employee":1,
"Class":"test 1",
"Comp":"test 1",
"Type":"test 1"
},
{
"Employee":2,
"Class":"test 2",
"Comp":"test 2",
"Type":"test 2"
}
]
Convert array into json string or make dictionary of post data than convert it into json string and post string to server.

Apparently you will have to form a body like this:
[
{
"Employee":1,
"Class":"test 1",
"Comp":"test 1",
"Type":"test 1"
},
{
"Employee":2,
"Class":"test 2",
"Comp":"test 2",
"Type":"test 2"
}
]

replace you string body
NSString * strBody = #"Employee = 1 & Class = tes & Comp = test & Type = Fixed"
to
NSString * strBody = #"Employee=1&Class=tes&Comp=test&Type=Fixed"

Related

Google Place api URL iOS

I am creating an app that uses Google Place. Before I used to use Yahoo's api and had to use a url that was responsible for local search that was provided by yahoo. The url was following:
http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=SF0DVEvV34G4GnXEDU4SXniaDebJ_UvC1G1IuikVz3vpOJrBpyD.VqCJCVJHMh99He3iFz1Rzoqxb0b7Z.0-
Now since yahoo's api is discontinued I have decided to switch over to Google Place. But I cannot find an Url to use. I just dowlod the framework and use the api key. Where can I find such url for Google Place.
Register for the Google Places API by following the linke provided below:
https://code.google.com/apis/console
Refer Code Link for places Auto Search
https://github.com/AdamBCo/ABCGooglePlacesAutocomplete
NSString *const apiKey = #"*****23xAHRvnOf2BVG8o";
NSString * searchWord = #"search some place "
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&types=establishment|geocode&radius=500&language=en&key=%#",searchWord,apiKey];
pragma mark - Network Methods
-(void)retrieveGooglePlaceInformation:(NSString *)searchWord withCompletion:(void (^)(BOOL isSuccess, NSError *error))completion {
if (!searchWord) {
return;
}
searchWord = searchWord.lowercaseString;
self.searchResults = [NSMutableArray array];
if ([self.searchResultsCache objectForKey:searchWord]) {
NSArray * pastResults = [self.searchResultsCache objectForKey:searchWord];
self.searchResults = [NSMutableArray arrayWithArray:pastResults];
completion(YES, nil);
} else {
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&types=establishment|geocode&radius=500&language=en&key=%#",searchWord,apiKey];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jSONresult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (error || [jSONresult[#"status"] isEqualToString:#"NOT_FOUND"] || [jSONresult[#"status"] isEqualToString:#"REQUEST_DENIED"]){
if (!error){
NSDictionary *userInfo = #{#"error":jSONresult[#"status"]};
NSError *newError = [NSError errorWithDomain:#"API Error" code:666 userInfo:userInfo];
completion(NO, newError);
return;
}
completion(NO, error);
return;
} else {
NSArray *results = [jSONresult valueForKey:#"predictions"];
for (NSDictionary *jsonDictionary in results) {
}
//[self.searchResultsCache setObject:self.searchResults forKey:searchWord];
completion(YES, nil);
}
}];
[task resume];
}
}

Post request with raw body using NSURLSession

I have stuck here. Below is my code for Post request with raw body using NSURLSession. I got response = NULL and no error.
NSString* stringRequest = #"https://chocudan.com/api/shops/by_ids";
NSURL* urlRequest = [NSURL URLWithString:stringRequest];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:urlRequest];
request.HTTPMethod = #"POST";
NSString* bodyRequest = #"563c268b84ba489c4729f149";
//I have to tried a base64 convert here but still not work.
//request.HTTPBody = [NSData base64DataFromString:bodyRequest];
request.HTTPBody = [bodyRequest dataUsingEncoding:NSUTF8StringEncoding];
NSURLSessionConfiguration* configureSession = [NSURLSessionConfiguration defaultSessionConfiguration];
configureSession.HTTPAdditionalHeaders = #{#"Content-Type" : #"application/json charset=utf-8",
#"Content-Lenght" : #"180"};
NSURLSession* session = [NSURLSession sessionWithConfiguration:configureSession];
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSHTTPURLResponse* respHttp = (NSHTTPURLResponse*) response;
if (!error && respHttp.statusCode == 200) {
NSDictionary* respondData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSLog(#"%#", respondData);
}else{
NSLog(#"%#", error);
}
}];
[dataTask resume];
I have to try with postman and everything work fine. This is pictures.
Thank in advance.
Try changing it too
NSArray* bodyArray = #[#"563c268b84ba489c4729f149"]
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:bodyArray
options:NSJSONWritingPrettyPrinted error:&error];
request.HTTPBody = jsonData;
My raw data was like :
{
"email":"test#gmail.com",
"password":"12345678"
}
and what I did is :
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:#"test#gmail.com" forKey:#"email"];
[dict setValue:#"12345678" forKey:#"password"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:NSJSONWritingPrettyPrinted error:&error];
request.HTTPBody = jsonData;
This fixed it for me:
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = ["Content-Type" : "text/plain"]
I guess that it was not data that was null but respondData was null?
That is because your service sends an Array with exactly one Object. JSONSerialisation creates an NSArray from that with one NSDictionary in it. The dictionary has the keys _id, contact and so on.
So it is
NSArray* respondData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
BTW
NSHTTPURLResponse* respHttp = (NSHTTPURLResponse*) response;
does not make much of a sense but does not harm either.
With respect to the body of your request, see mihir's answer. He is just right.
It may help you understanding mihir's point when you do this:
NSString* bodyRequest = #"[563c268b84ba489c4729f149]";
However, this is rather quick & dirty but may help you understanding the principles. Once understood you will certainly follow mihir's suggestion.
If you want to post raw, and param is a format of NSString, you only need to do this:
NSData *param_data = [encry_str dataUsingEncoding:NSUTF8StringEncoding];
murequest.HTTPBody = param_data;
If we can’t get anything from that response, notice that the response serializer is correct. Any additional settings, please deal it with server.

the arabic string is not readable when load json

Code:
+(id)loadJSONDataFromURL:(NSString *)urlString{
MsgsHelper *msg=[[MsgsHelper alloc]init];
// This function takes the URL of a web service, calls it, and either returns "nil", or a NSDictionary,
// describing the JSON data that was returned.
NSError *error;
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// Call the web service, and (if it's successful) store the raw data that it returns
NSURLResponse *response = nil; //
NSData *data = [ NSURLConnection sendSynchronousRequest:request returningResponse: &response error:&error ];
//here we get the respond from NSURLResponse and then we check for the statusCode //1
//200 is ok,, 0 is no internet connection else is server error //2
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;//1
//any warning like this one with integers shuold add the casting (int)
int statCode = (int)[httpResponse statusCode];//2
if(statCode == 200){
if (!data)
{
//NSLog(#"Download Error: %#", error.localizedDescription);
return nil;
}
// Parse the (binary) JSON data from the web service into an NSDictionary object
id dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (dictionary == nil) {
//NSLog(#"JSON Error: %#", error);
return nil;
}
return dictionary;
}else if(statCode == 0){
[msg alertStatus:NSLocalizedString(#"No internet", #"Message") :#"" :0 ];
return nil;
}else{
//Server Error
//NSLog(#"Server Error");
[msg alertStatus:NSLocalizedString(#"Server Error", #"Message") :#"" :0 ];
return nil;
}}
the problem on result as below:
results: (
{
"Name" = "\U0633\U0639\U0648\U062f \U0639\U0628\U062f\U0627\U0644\U0639\U0632\U064a\U0632 \U064a\U0646 \U062c\U062f\U064a\U062f";
"location" = CENTER;
}
)
maybe need to dataUsingEncoding to read arabic string, but how do it.
Thanks,

NSMutableURLRequest returning JSON with empty sub-arrays

I have created a method that uses NSMutableURLRequest to request and receive JSON from a RESTful API running on a remote machine. The request successfully returns some JSON, but the returned sub-arrays in the JSON (see tasks: []) are empty.
The JSON returned from the API is:
{
"error":false,
"tasks":[
{
"id":1,
"task":"Get Milk",
"status":0,
"createdAt":"2014-08-09 12:29:15"
},
{
"id":2,
"task":"Call Mom",
"status":0,
"createdAt":"2014-08-09 12:46:52"
},
{
"id":3,
"task":"Call Dad",
"status":0,
"createdAt":"2014-08-09 12:47:04"
},
{
"id":4,
"task":"Study",
"status":0,
"createdAt":"2014-08-09 12:47:08"
}
]
}
The method that utilizies NSMutableURLRequest (proper parameters being passed is assumed) is:
-(NSDictionary *) apiRequestWithEndpoint:(NSString *) endpoint
withParams:(NSDictionary *) params
withHTTPHeaders:(NSDictionary *) headers
withHTTPMethod:(NSString *) method
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:endpoint]];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:method];
//set headers
for (id key in headers) {
[request setValue:[headers valueForKey:key] forHTTPHeaderField:key];
}
//set paramaters in request body
NSMutableString *requestBody = [[NSMutableString alloc] init];
int keyIndex = 0;
for (id key in params) {
if (keyIndex == 0) {
[requestBody appendFormat:#"%#=%#", key, [params valueForKey:key]];
} else {
[requestBody appendFormat:#"&%#=%#", key, [params valueForKey:key]];
}
keyIndex++;
}
[request setHTTPBody:[requestBody dataUsingEncoding:NSUTF8StringEncoding]];
NSURLResponse *response;
NSError *NSURLError = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&NSURLError];
if (NSURLError) {
NSLog(#"Error: %# Cancelling operation.", NSURLError);
return nil;
}
NSError *NSJSONSerializationError = nil;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&NSJSONSerializationError];
if (NSJSONSerializationError) {
NSLog(#"Error: %# Cancelling operation.", NSJSONSerializationError);
return nil;
}
NSLog(#"Data: %#",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
return responseJSON;
}
Notice the 4th last line that logs the returned NSData from the NSMutableURLRequest, the output is:
Data: {"error":false "tasks":[]}
The code that calls the above method:
NSString *getAllTasksEndpoint = #"http://developmentVPS.com/TaskList-API/v1/tasks";
NSString *apiKey = #"A Valid API Key";
NSDictionary *headers = [[NSDictionary alloc] initWithObjectsAndKeys:apiKey, #"Authorization", nil];
NSDictionary *responseJSON = [self apiRequestWithEndpoint:getAllTasksEndpoint
withParams:nil
withHTTPHeaders:headers
withHTTPMethod:#"GET"];
It is my understanding that the entire data returned from the request should be logged in that NSLog call, but "tasks" is empty. I am new to iOS development, so I may be missing something simple. Does anybody see anything I am missing here?

NSURLConnection wrong order

I have a NSURLConnection (two of them), and they're running in the wrong order.
Here's my method:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
}
}
else {
NSLog(#"error: %#", error);
}
}];
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:#"POST"];
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)#" ",
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
So, it's two NSURLConnection's that are added to the [NSOperationQueue mainQueue]. What my output is showing me is that the second NSURLConnection is running before the first one. So it tries to go to the page where I download data before I'm logged in, so it (obviously) returns a "You're not logged in" error.
How do I schedule them one after another?
The issue, as I suspect you have realized, is that you're doing asynchronous network requests (which is good; you don't want to block the main queue), so there's no assurance of the order they'll finish.
The quickest and easiest answer is to simply put the call to the second request inside the completion block of the first one, not after it. You don't want to be making that second one unless the first one succeeded anyway.
To keep your code from getting unwieldy, separate the login from the request for main page. And you can use the completion block pattern which is common with asynchronous methods. You add a parameter to loginToMistarWithPin that specifies what it should do when the request finishes. You might have one completion block handler for success, and one for failure:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password success:(void (^)(void))successHandler failure:(void (^)(void))failureHandler {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
// assuming you validated that everything was successful, call the success block
if (successHandler)
successHandler();
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
if (failureHandler)
failureHandler();
}
}
else {
NSLog(#"error: %#", error);
if (failureHandler)
failureHandler();
}
}];
}
- (void)requestMainPage {
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[requestHome setHTTPMethod:#"GET"]; // this looks like GET request, not POST
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
Then, when you want to login, you can do something like:
[self loginToMistarWithPin:#"1234" password:#"pass" success:^{
[self requestMainPage];
} failure:^{
NSLog(#"login failed");
}];
Now, change those successHandler and failureHandler block parameters to include whatever data you need to pass back, but hopefully it illustrates the idea. Keep your methods short and tight, and use completion block parameters to specify what an asynchronous method should do when it's done.
Can you check the below link. It is about forcing one operation to wait for another.
NSOperation - Forcing an operation to wait others dynamically
Hope this helps.

Resources