I am having an issue trying to fetch JSON page from one of our company's site that requires authentication.
- http://xyz.com - requires authentication
- I need to fetch data from http://xyz.com/jsonpage1
- In View DidLoad, I send user and pwd for login to establish session
- Then, I have a button that would request JSON.
This sequence doesn't work (meaning if the session loading code is in a different routine than the json loading code). If I have both codes in same routine like a view didLoad, then it seems to recognize my credentials and get JSON back. Strange! What am I missing? How is supposed to work? I thought establishing the session will create the cookie one time and no need to bother with it again? Am I losing the cookie somehow when I click the button?
-(void)viewDidLoad
{
[self establishSession];
}
-(void)establishSession{
//
//Login Session
//
NSURL *url = [NSURL URLWithString:#"http://xyz.com/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *post = [NSString stringWithFormat:#"username=%#&password=%#",#"abc",#"123"];
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
[request setValue:[NSString stringWithFormat:#"%d",[postData length]] forHTTPHeaderField:#"Content-Length"];
[request setTimeoutInterval:15];
[request setHTTPBody:postData];
[request setHTTPMethod:#"POST"];
urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[urlConnection start];
}
- (IBAction)getJSON:(id)sender
{
NSError *error = nil;
resultsView.text =#"";
[self establishLoginSession]; //I have to have this line here to get it to work ?????
//get JSON
NSURL *jurl = [NSURL URLWithString:#"http://xyz.com/jsonPage1"];
NSData *jdata = [NSData dataWithContentsOfURL:jurl options:NSDataReadingUncached error:&error];
NSDictionary* jsonDict = [NSJSONSerialization
JSONObjectWithData:jdata //1
options:kNilOptions
error:&error];
NSString *dataString = [[NSString alloc]initWithData:jdata encoding:NSUTF8StringEncoding];
resultsView.text = dataString;
}
//Not sure if I need the cookie??
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse*) response;
NSDictionary *fields = [HTTPResponse allHeaderFields];
if([fields valueForKey:#"Set-Cookie"])
cookie = [fields valueForKey:#"Set-Cookie"];
}
You can only make one request with a NSURLConnection object, so you should create it right before you're making the request.
Related
I have this code;
NSString *post = [NSString stringWithFormat:#"latitude=%lf&longitude=%lf&provider=network&accuracy=%lf&hiz=%lf&retrieveTime=%#",
locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude,
locationManager.location.horizontalAccuracy,
locationManager.location.speed,
dateString];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSString *sUrl = [[NSUserDefaults standardUserDefaults] stringForKey:#"serviceUrl"];
NSString *swoclString = [NSString stringWithFormat:#"%#/saveLocation.php", sUrl];
[request setURL:[NSURL URLWithString:swoclString]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(conn) {
NSLog(#"Location Save Successfully");
} else {
NSLog(#"Location Save Error");
}
I can receive the data in the server side. And on the iOS side I can see the log "Location Save Successfully".
How can I receive the response from the server without implementing other methods?
Use NSURLSession instead of NSURLConnection to post your data to the Server. Below is an example how you can post JSON.
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"<YOUR-URL-STRING>"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:120.0];
[request setHTTPMethod:#"POST"];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"application/json" forHTTPHeaderField:#"Accept"];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:<YOUR_JSON_DATA> options:NSJSONWritingPrettyPrinted error:&error];
NSString *tmp = [[NSString alloc]initWithData:postData encoding:NSUTF8StringEncoding];
[request setHTTPBody:postData];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse *resp = (NSHTTPURLResponse *) response;
NSLog(#"%li",(long)resp.statusCode);
if(resp.statusCode==200){
NSMutableArray *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
}];`
The block is used to return the response by the server. For example the HTTP-Status Code and the response data. If you use json you can convert the Data with the NSJSONSerialization class.
If you are using latest ios coding standards you must have to use URLSession object to send any request to the API calls because DEPRECATED: The NSURLConnection class should no longer be used. NSURLSession is the replacement for NSURLConnection. But still, if you want to continue with an old procedure, there are three ways to send API request.
P1:
-(void)procedure1{
NSURLRequest *requestObject = nil; /** replace with your request object **/
NSURLResponse *serverResponse = nil;
NSError *connectError = nil;
/* thread bloker request */
NSData *responseData = [NSURLConnection sendSynchronousRequest:requestObject returningResponse:&serverResponse error:&connectError];
if (connectError == nil) {
//parse server response data (i.e, json or xml)
}else{
/* handle connection error */
}
}
P2:
-(void)procedure2{
NSURLRequest *requestObject = nil; /** replace with your request object **/
/* thread free request */
[NSURLConnection sendAsynchronousRequest:requestObject queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (connectionError == nil) {
//parse server response data (i.e, json or xml)
}else{
/* handle connection error */
}
}];
}
P3:
the last one is a bit different than the other two,
#interface TestViewController ()<NSURLConnectionDelegate>
#property (nonatomic, retain) NSMutableData* responseData;
#end
-(void)procedure3{
NSURLRequest *requestObject = nil; /** replace with your request object **/
NSURLConnection *connectionObject = [NSURLConnection connectionWithRequest:requestObject delegate:self];
[connectionObject start];
}
here in this procedure you are required to invoke NSURLConnectionDelegate methods
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.responseData setLength:0];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
NSString* responseString = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
connection = nil;
}
I've search and try many different solutions but without luck.
I am trying to make a JSON Request to my server, it works for sure because I've tested it in PHP (simple call, it receives string name and string password and check into the database if the user is correct). The request should receive back a JSON with property "success" only (which could be "true" or "false").
Here is my code:
- (void)logonService:(NSString *) name widthArg2:(NSString *) password {
// Create the request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://46.51.169.145/ios/index.php/user/login/"]];
// Specify that it will be a POST request
request.HTTPMethod = #"POST";
//setting json fields
[request setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
//prepare output data
NSString *in1;
NSDictionary *outputData = [NSDictionary dictionaryWithObjectsAndKeys:in1, #"success", nil];
NSError *error = nil;
NSData *jsonOutputData = [NSJSONSerialization dataWithJSONObject:outputData options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonOutputString = [[NSString alloc] initWithData:jsonOutputData encoding:NSUTF8StringEncoding];
//set json string to body data
NSData *requestInputBodyData = [jsonOutputString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody: requestInputBodyData];
//prepare input data
NSString *input = [NSString stringWithFormat:#"&name=%#&password=%#",name,password];
//Encode the post string using NSASCIIStringEncoding and also the post string you need to send in NSData format.
NSData *inputData = [input dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
//calculate length of post data
NSString *inputLength = [NSString stringWithFormat:#"%d",[inputData length]];
//Set HTTP header field with length of the post data.
[request setValue:inputLength forHTTPHeaderField:#"Content-Length"];
//encode type
//[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Current-Type"];
//add it to http body
[request setHTTPBody:inputData];
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(conn){
NSLog(#"Connection Successful");
}else{
NSLog(#"Connection could not be made");
}
}
The delegate DidReceiveData fires correctly but the result is always NIL:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *jsonResponseData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"RESULT1: %#", jsonResponseData);
[_responseData appendData:data];
}
Thank you, hope someone can help me!
thanks a lot for the comments, I finally fix it, and after that I decided to starting using a JSON library --> https://github.com/stig/json-framework/
This is how I finally have the code:
//prepare connection
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#user.php", _urlServer]];
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
[data setObject:#"login" forKey:#"action"];
[data setObject:username forKey:#"username"];
[data setObject:password forKey:#"password"];
//start connection
// Create the request, if there is a connection going on just cancel it.
[_connection cancel];
//initialize new mutable data
NSMutableData *receivedData = [[NSMutableData alloc] init];
_receivedData = receivedData;
//initialize the url which will be fetched
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[url standardizedURL]];
//set http method
[request setHTTPMethod:#"POST"];
//initialize a post data
NSString *dataString = [[NSString alloc] init];
for(id key in data) {
id value = [data objectForKey:key];
//keys string
NSString *newData = [NSString stringWithFormat:#"&%#=%#", key, value];
dataString = [dataString stringByAppendingString: newData];
}
//set request content type we MUST set this value.
[request setValue:#"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
//set post data of request
[request setHTTPBody:[dataString dataUsingEncoding:NSUTF8StringEncoding]];
//initialize a connection from request
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
_connection = connection;
//NSLog(#"Sending request with parameters: %#", dataString);
//begin the connection
[_connection start];
And its working like a charm. Next step is to authenticate somehow, right now connection is open to the world.
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.
I'm trying to make a POST request using NSURLConnection. I use Charles to debug and Charles every time says that the method is GET. I've tried all different ways and can't get it to work. I am NOT using JSON.
-(void)getList
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://example.com/api/getList"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *radius = #"15";
NSString *latitude = #"-117.820833";
NSString *longitude = #"34.001667";
NSString *parameters = [NSString stringWithFormat:#"longitude=%#&latitude=%#&radius=%#", longitude,latitude, radius];
NSLog(#"PARAMS = %#", parameters);
NSData *data = [parameters dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/plain" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:data];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *responseString = [[NSString alloc]initWithData:result encoding:NSUTF8StringEncoding];
NSLog(#"RESULT = %#", responseString);
}
Does anybody know what am I doing wrong? When I access my web service it seems like I'm not posting anything. I'm getting empty response.
Please help with any ideas. I pretty much have to make a simple POST request. Maybe someone can help me debug this better.
If the server is redirecting your request for some reason (perhaps authentication) then the POST information can get lost.
This is my code.
- (void)loadData:(NSString *)url {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"connection found---------");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"reciving data---------");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"connection fail---------");
[self.pddelegate connectionError];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"data posting done---------");
[self.pddelegate dataPosted];
}
It is not working if url become bigger and give connection fail in logs.
Like
url=#".......order_details&admin=29&tableid=89&waiter_id=18&items=MzQ6MSwxMToxLDMzOjEsNjc6MSwzOToxLDY5OjEsNTY6MSw2ODoxLDg6MSw1NToxLDYyOjEsNzY6MSw0MToxLDIwOjEsNjE6MQ=="
see this SO post for get type request length What is the maximum length of a URL in different browsers?
for sending big string use POST type request instead of GET type.
We have there are two methods for sending data.
1. GET Method : Which is used for fixed length or limited length of string only.
2. POST Method : Which is used to send more string while comparing get method.
I have given the example Using PostMethod.
NSString *post =[[NSString alloc] initWithFormat:#"%#",YourString];
NSURL *url=[NSURL URLWithString:*#"YourURL like www.google.com"*];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue: #"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
request.timeoutInterval = 60;
NSError *error = nil;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request
returningResponse:&response error:&error];
NSString *errStr = _stringEmpty;
#try { errStr = [error localizedDescription]; }#catch (NSException * exception){ }
If any error occur errStr will show the error.
In the past, I have used some URL's that are around 2000 characters in length in iOS with no problem. NSURL, NSURLRequest, and NSURLConnection all managed just fine. If your URL is shorter than that, the problem is probably not due to its length, but instead related to the way the URL is constructed.