I'm trying to persist data from a microsoft web service call to a file when my app starts up. If the app is able to complete the webservice request, it's storing the data in an NSData object. Assuming the data has been successfully requested and stored, I want to execute certain code that I would NOT want to if the webservice is unsuccessful.
My webservice request is as follows:
NSMutableURLRequest *request1 = [[NSMutableURLRequest alloc]init];
[request1 setURL:[NSURL URLWithString:#"---URL---"]];
[request1 setHTTPMethod:#"GET"];
NSURLResponse *request1Response;
NSData *request1Handler = [NSURLConnection sendSynchronousRequest:request1 returningResponse:&request1Response error:nil];
NSString *request1Reply = [[NSString alloc]initWithBytes:[request1Handler bytes] length:[request1Handler length] encoding:NSASCIIStringEncoding];
NSData *data1 = [request1Reply dataUsingEncoding:NSUTF16StringEncoding];
So basically, the response is dropped into that data1 object.
When connected to the internet, the request executes fine. The code that follows is wrapped in a if(data1){ conditional to make sure that the webservice request is successful before executing it. The problem is that when I disconnect from the internet(and cut off access to that webservice), the code inside the conditional is still being executed.
I tried comparing data1 to nil, logging data1 to do a direct comparison of the contents, etc, but I gather that that data1 object isn't nil; it probably contains some sort of failure message that I have thus far been unable to access. What can I do in the conditional or in the webservice request itself to figure out when the request fails?
Create an NSError object and pass it as argument to the sendSynchronousRequest: method, then if there is network or another error, the err object will populated with error information hence it will not be nil. That means you can check if(!err)contiune else there is an error
check the code:
NSMutableURLRequest *request1 = [[NSMutableURLRequest alloc]init];
[request1 setURL:[NSURL URLWithString:#"http://www.google.com"]];
[request1 setHTTPMethod:#"GET"];
//object where error will be saved
NSError *err;
NSURLResponse *request1Response;
NSData *request1Handler = [NSURLConnection sendSynchronousRequest:request1 returningResponse:&request1Response error:&err];//pass the err here by reference
NSString *request1Reply = [[NSString alloc]initWithBytes:[request1Handler bytes] length:[request1Handler length] encoding:NSASCIIStringEncoding];
NSData *data1 = [request1Reply dataUsingEncoding:NSUTF16StringEncoding];
and then you can check here:
if (err){
NSLog(#"error: %#", err);
}
You should at least be checking for an error response by populating the error pointer parameter.
Ideally you should be using a different API which gives you access to more details such as the response HTTP status code which you should be using to determine what happened even if you did get something which looks like success.
I have an AWS EC2 instance and an app that I created. The app is for people who get migraines (tracks info, tells them what their trigger(s) are). Now I want to be able to send user input from my application to a server so that I can see trends. I am having difficulty connecting to the server and finding out how I would be able to write files to the server.
I have written this method:
- (void) sendDataToServer:(NSString *)url :(NSString *)key : (NSString *) content{
// define your form fields here:
//NSString *content = #"field1=42&field2=Hello";
NSString *address = [NSString stringWithFormat:#"ssh -i %# %#", key, url];
NSLog(#"%#", address);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:address]];
[request setHTTPMethod:#"POST"];
NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:contentData];
NSString *postLength = [NSString stringWithFormat:#"%d",[contentData length]];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
// generates an autoreleased NSURLConnection
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn){
NSLog(#"connection");
}
//[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
//[self doSomethingWithData:data];
if (error){
NSLog(#"ERROR");
}
}];
}
I put the private key from my key pair into the app. How would I use that to connect? Should I not be using my private key? Should I be doing this differently?
Should I be doing this differently?
Absolutely, 100%, YES. You don't want to let people SSH into your server, especially by embedding your private key into an app binary. It's crazy easy for someone to get it, then wreak havoc upon your server.
Don't do this.
Instead, I would get a web server like Apache running on your instance (it's trivial), and write an application (in PHP, Rails (with Passenger), Python, whatever) that saves files to the server's hard drive. You'll also want to get an Elastic IP address so that it stays constant, as ashack mentioned.
In your iOS app, you'll want to send a POST request to your server. See Sending an HTTP POST request on iOS, it's essentially what you're doing now.
Don't publish your private SSH key. It's private for a good reason.
I want to like and comment in my iOS application.But the problem is whenever I call my API the response comes in the form of this `error:message:(#200)'. App does not have permission to make this call and sometimes it will give input parameter is required.The permissions i give are 'basic_info','email','user_likes' and 'read_stream'. I am passing object id and access token in my like and comment API.
Like API code:
NSString *theWholeUrl = [NSString stringWithFormat:#"https://graph.facebook.com/%#/likes?access_token=%#",self.friendId,[FBSession activeSession].accessTokenData.accessToken];
NSLog(#"Value of theWholeUrl%#",theWholeUrl);
NSURL *facebookUrl = [NSURL URLWithString:theWholeUrl];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:facebookUrl];
[req setHTTPMethod:#"POST"];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&err];
NSString *content = [NSString stringWithUTF8String:[responseData bytes]];
You need the publish_actions permission to be able to like and comment on content programmatically via the API.
I want to send my UITextfields data to a server.
I want to post data but the server showing error message to me.
Please check my code:
...
NSURL *url=[NSURL URLWithString:#"http://projectsatseoxperts.net.au/fishing/api/postRegister.php"];
NSString *post =[[NSString alloc] initWithFormat:#"FirstName=%#&LastName=%#userName=%#&Email=%#Phone=%#&Address=%#Password=%#&ConfirmPassword=%#",
txt_firstname.text,txt_lastname.text,txt_username.text,txt_email.text,txt_phone.text,txt_address.text,txt_password.text,txt_confirmpassword.text];
NSLog(#"Post is: %#",post);
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSLog(#"postData is: %#",postData);
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSLog(#"postLength is: %#",postLength);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
//[request setValue:#"http://projectsatseoxperts.net.au/fishing/api/postRegister.php" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSLog(#"request is: %#", [request allHTTPHeaderFields]);
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"urlData is: %#",urlData);
NSString *data=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"%#",data);
}
After post the details the values will come here - http://projectsatseoxperts.net.au/fishing/api/register.php
Any idea or suggestions would be highly welcome.
A couple of observations:
The way you phrase your question, you would seem to be suggesting that you're trying to create a application/x-www-form-urlencoded request. If so, you should specify your Content-Type accordingly:
[request setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
If doing a application/x-www-form-urlencoded request, then you must percent escape the data that you post, using CFURLCreateStringByAddingPercentEscapes (note, not stringByAddingPercentEscapesUsingEncoding). If any of your fields included any reserved characters, your query would fail.
- (NSString *)percentEscapeURLParameter:(NSString *)string
{
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
NULL,
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
}
Also, your post string is missing a few ampersands. I might solve this problem by using a dictionary:
NSDictionary *dictionary = #{#"FirstName" : txt_firstname.text,
#"LastName" : txt_lastname.text,
#"userName" : txt_username.text,
#"Email" : txt_email.text,
#"Phone" : txt_phone.text,
#"Address" : txt_address.text,
#"Password" : txt_password.text,
#"ConfirmPassword" : txt_confirmpassword.text};
And then build the post variable, invoking percentEscapeURLParameter for each value, like so:
NSMutableArray *postArray = [NSMutableArray array];
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
[postArray addObject:[NSString stringWithFormat:#"%#=%#", key, [self percentEscapeURLParameter:obj]]];
}];
NSString *post = [postArray componentsJoinedByString:#"&"];
By the way, those field names look suspect (with lowercase "u" in "userName"; often they're all lowercase field names). Are you sure about those field names?
Beyond that, you have to show us the error that you're getting.
Your "post" strings format look to be incorrect. You are missing some "&" in between certain fields i.e between "LastName" and "userName". Check your string as the server may not recognise the values in the string. Unless there is a specific reason for this.
Your Request is proper.. just check the content Type and Encoding of your post data.. Also do consult with the server team for exact data format they expect from you..
I suspect that since the API is returning XML, it is expecting XML in the HTTP POST. Contact the API developer to find out what data formats the API supports and the schema it expects.
There a number of issues with your code:
Potentially incorrect character encoding:
In your code:
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
you allow a lossy conversion from the character encoding of the original string to the one used for your post data. This will lead to incorrect parameters when they contain non-ASCII characters.
No Content-Type header set
Since you didn't set a content type, your data will be treated by the server as an unstructured text of ASCII characters, e.g. Content-type: text/plain; charset=us-ascii.
You probably want to use application/x-www-form-urlencoded, or better application/json - if the server accepts that MIME type.
When you set a Content-Type you also need to ensure your parameters are properly encoded according the Content-Type you set.
In order to solve these issues, I would suggest to try application/json as Content-Type and encode your parameters as JSON. Using Content-type: application/x-www-form-urlencoded is also possible, but this requires a much more elaborated encoding algorithm. Just try JSON:
So, instead of having this ugly string
NSString *post =[[NSString alloc] initWithFormat:#"FirstName=%#&LastName=%#userName=%#&Email=%#Phone=%#&Address=%#Password=%#&ConfirmPassword=%#",
txt_firstname.text,txt_lastname.text,txt_username.text,txt_email.text,txt_phone.text,txt_address.text,txt_password.text,txt_confirmpassword.text];
create a corresponding NSDictionary object. Then serialize it to a NSData object containing the JSON using NSJSONSerialization. Use this data object for your body, and set Content-Type: application/json.
I have an app that uses webView. In the home screen of a website I want to login using username and password entered by the user in the app's settings option. Currently I have this code which I saw in solution to a similar question asked on this forum. But it isn't working (neither it did for the other guy).
-(IBAction)cachepressed:(id)sender{
NSString *baseurl=[[NSUserDefaults standardUserDefaults] stringForKey:#"url_preference"];
NSString *username= [[NSUserDefaults standardUserDefaults] stringForKey:#"name_preference"];
NSString *password= [[NSUserDefaults standardUserDefaults] stringForKey:#"pswrd_preference"];
NSString* content = [NSString stringWithFormat:#"username=%#&password=%#", username, password];
NSData *data=[content dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postlength=[NSString stringWithFormat:#"%d",[data length]];
NSString *loginpage= [baseurl stringByAppendingString:#"/index.php?title=Special:UserLogin"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:loginpage]];
[request setHTTPMethod:#"POST"];
[request setValue:postlength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:data];
NSError *error=nil;
NSURLResponse *response=nil;
NSData *result=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *HTMLString = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
[webView loadHTMLString:HTMLString baseURL:[NSURL URLWithString:loginpage]];
}
I am not too sure about the two lines of code starting with [request setValue...]. Can somebody suggest a solution to this? It would be a great help. Thanks in anticipation.
This depends a lot on how the authentication is done on the website.
Based on what I can figure from your question, the code you posted sends values for the fields named "username" and "password" to the index.php?title=Special:UserLogin page using POST.
You need to make sure that everything is set accordingly.
1. Are your fields name the same on the website?
Maybe the login form uses different field names, not username and password. Check the source code and see if the input names are indeed "username" and "password"
2. Does your host allow posting data from a different source?
I used to set mine so no POST request would work if they didn't originate from my server, so POSTing data from an iPad would not have functioned.
Is this the case for you too?
3. The login process is really done by posting data to that page?
Maybe on the website the authentication is done using AJAX on a different php page and then you get redirected to index.php?title=Special:UserLogin, I've seen such cases in the past.
Bottom line is that you need to know exactly how the login is done on the website before doing it inside a webview. Correct me if I'm wrong, but based on your post it doesn't seem to be the case here