POST and multiple submit buttons on form - iphone

NSString *reqURL = [NSString stringWithFormat:#"%#/login",SERVER_URL];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:reqURL]];
[req setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
NSData *myRequestData = [NSData dataWithBytes:[#"username=whatever&password=whatever" UTF8String] length: [#"username=whatever&password=whatever" length]];
[req setHTTPMethod: #"POST"];
[req setHTTPBody: myRequestData];
NSData *returnData = [NSURLConnection sendSynchronousRequest:req returningResponse: nil error: nil];
NSString *html = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
I got this code from another question I asked. But what happens if there is more than one submit button. I really have no idea how to ask this question. An example of such situation is on the logout page for this site. There are no fields to enter data into, but there are 2 submit buttons.
How can I "simulate clicking" on one of those buttons using code like the above (so not using a UIWebView)

The way those forms usually tell which button was pressed is by naming their buttons and checking the value. Simply put, a basic page receiving form data will check if a form was even submitted by checking if ($_POST['submit'] == "Send!") which tells the page that the user got there by pressing the button. The same concept is used when deciding what button was pressed.
if ($_POST["submit"] == "Send!") addDataToDB();
else if ($_POST["submit"] == "Update!") updateUser();
else if ($_POST["submit"] == "Remove me!") removeUser();
So now, what you need to do is check the source of the html page with the form and find out the name and value of the submit button you want to simulate and add that data to your POST body data in your request
Update: Oops! misunderstood your question, thought you meant multiple submit buttons in one form on one page, but now i think you meant one form going to another "confirmation" form...In your didRecieveData delegate method you will need to store all the html you get and in your didFinishLoading delegate method you will need to pull out any hidden field names & values and then create a new request with them as your POST data and the url being the "action" url of the form

Related

Box File Upload API using Objective C

I have been trying out for a while using Box 2.0 API to upload a file from Objective C client to my Box folder. I've read a few posts from:
how to send form data in a programmatic file upload in box api 2.0
API 2.0 how to upload file with POSTMAN?
I've tried successfully using the Curl, as mentioned in the documentation, but always get a 404 when trying to create a NSMutableUrlRequest.
This is my code:
NSURL *URL = [NSURL URLWithString:#"https://api.box.com/2.0/files/content"];
urlRequest = [[NSMutableURLRequest alloc]
initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30];
[urlRequest setHTTPMethod:#"POST"];
AppDelegate *appDelegate = [AppDelegate sharedDelegate];
NSString *p = [NSString stringWithFormat:#"BoxAuth api_key=%#&auth_token=%#",API_KEY,appDelegate.boxAuthToken];
[urlRequest setValue:p forHTTPHeaderField:#"Authorization"];
[urlRequest setValue:#"multipart/form-data, boundary=AaB03x" forHTTPHeaderField:#"Content-Type"];
NSString *postBody = #"--AaB03x"
#"content-disposition: form-data; name=\"filename\"; filename=\"test.txt\";"
#"folder_id=466838434"
#"Content-type: text/plain"
#""
#"testing box api 2.0"
#""
#"--AaB03x--";
NSData *data = [postBody dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setHTTPBody:data];
[urlRequest setValue:[NSString stringWithFormat:#"%d",[data length]] forHTTPHeaderField:#"Content-Length"];
There are a couple of problems that I see with the way you're constructing the postBody. Having newlines between string literals in your code simply concatenates them. You actually need to have carriage return and line feed to separate different parts of your HTTP body. Also, you mashed both of your form elements in one. The file and folder_id are two separate form elements. You could try something like this:
NSString *postBody = #"\r\n--AaB03x\r\n"
"Content-Disposition: form-data; filename=\"test.txt\"\r\n"
"Content-Type: text/plain\r\n\r\n"
"testing box api 2.0"
"\r\n--AaB03x\r\n"
"Content-Disposition: form-data; name=\"folder_id\";\r\n\r\n"
"0"
"\r\n--AaB03x--\r\n\r\n";
I think that should work provided everything else is set up properly.
Use http://allseeing-i.com/ASIHTTPRequest/
It makes dealing with multipart forms much easier!

How to send HTTP POST request with gziped content?

I'm developing iPhone app and manually constructing POST requests. Currently, need to compress JSON data before sending it, so looking how to tell a server the content is compressed. Setting content type header to gzip might be not acceptable because server expects JSON data. I'm looking for transparent solution, something like just to add some header telling JSON data is compressed into gzip.
I know, the standard way is to tell the server that the client accepts encoding, but you need to make GET request with accept encoding header first. In my case, I want to post the data already encoded.
Include a Obj-C gzip wrapper, for example NSData+GZip, and use it to encode the body of your NSURLRequest. Also remember to set the Content-Encoding accordingly, so the webserver will know how to treat your request.
NSData *requestBodyData = [yourData gzippedData];
NSString *postLength = [NSString stringWithFormat:#"%d", requestBodyData.length];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"gzip" forHTTPHeaderField:#"Content-Encoding"];
[request setHTTPBody:requestBodyData];
Implmenting some general Method such as follows and setting appropriate Header might help you.
// constructing connection request for url with no local and remote cache data and timeout seconds
NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:callingWebAddress]];// cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:timoutseconds];
[request setHTTPMethod:#"POST"];
NSMutableDictionary *headerDictionary = [NSMutableDictionary dictionary];
[headerDictionary setObject:#"application/json, text/javascript" forKey:#"Accept"];
[headerDictionary setObject:#"application/json" forKey:#"Content-Type"];
//Edit as #centurion suggested
[headerDictionary setObject:#"Content-Encoding" forKey:#"gzip"];
[headerDictionary setObject:[NSString stringWithFormat:#"POST /Json/%# HTTP/1.1",method] forKey:#"Request"];
[request setAllHTTPHeaderFields:headerDictionary];
// allocation mem for body data
self.bodyData = [NSMutableData data];
[self appendPostString:[parameter JSONFragment]];
// set post body to request
[request setHTTPBody:bodyData];
NSLog(#"sending data %#",[[[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding]autorelease]);
// create new connection for the request
// schedule this connection to respond to the current run loop with common loop mode.
NSURLConnection *aConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//[aConnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
self.requestConnenction = aConnection;
[aConnection release];

Storyboard - Open view programmatically

I am currently building an Iphone app that is using storyboards. I know how to open new views with buttons via the ctrl+click method etc. The problem I have is that when the user clicks the button, I need to do some calculations and processing, as well as opening a web connection to pull data so I can populate the table in the next view but the view opens first before I can do any of this.
What I'm running into is the view is loading long before I am finished connecting to the web service and have calculated and stored the data for the table in the next view, so it loads blank. I need to either call the view in the button programmatically or somehow slow down the processes with some kind of "loading" screen but don't know how to do either. I guess if its possible to fill the data in the table after the view loads, that could work as well. (if its possible)
Any tips or articles that can point me in the right direction would be appreciated. I haven't found anything myself.
Thanks.
--connect method--
- (IBAction)connect:(id)sender {
//First begin by logging into the web service.
_email = self.logintxt.text;
// ---SOAP 1.1---
//large soap creation. edited for privacy etc.
NSString *soapMsg =
[NSString stringWithFormat:#"",_logintxt.text
];
//---print it to the Debugger Console for verification---
//NSLog(soapMsg);
NSURL *url = [NSURL URLWithString:
#""];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
//---set the headers---
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMsg length]];
[req addValue:#"" forHTTPHeaderField:#"Host"];
[req addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[req addValue:#"" forHTTPHeaderField:#"SOAPAction"];
[req addValue:msgLength forHTTPHeaderField:#"Content-Length"];
//---set the HTTP method and body---
[req setHTTPMethod:#"POST"];
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn) {
XMLData = [NSMutableData data];
}
[self performSelector:#selector(getXMLList) withObject:NULL afterDelay:2.0];
[self performSegueWithIdentifier:#"LoginSegue" sender:sender];
You can have your button or whatever linked to a method in your controller, and inside the method after your processing you can call performSegueWithIdentifier: to force the transition when you're done. This will automatically still call prepareForSegue: before the view appears.
I've done something similar to check login details on a login page in my tutorial here.
what I can suggest is to write the button action yourself. to achieve this you have to put stuff in your .h like
#interface MyClass : UIViewController {
IBOutlet UIButton *my_btn;
}
#property (nonatomic, retain) IBoutlet UIButton *my_btn;
- (IBAction)MyBtnTapped:(id)sender;
in your .m remember to
#synthesize my_btn;
then just link the action to your button by using IB, and voila'
the first step is done.
in your .m you can now implement a function MybtnTapped that deals with the data retrival and then opens up the new UIView fulfilled with your new data.

Serialized my in App "Shopping Cart" now trying to send it to a server using http Post - doesn't reach destination

I have a shopping cart in my app and an underlying data structure that I have serialized into an XML file. Im using the following code to place it on my server. However, nothing happens. Whe I check my server I donot find my file there. So I tried using just a string in place of the file and still the same. Nothing seems to be sent from the app to the server. Im running ths off the simulator.
Im wondering if there is anything wrong with this code.
CartSingleton *Cart = [CartSingleton getSingleton];
id xmlFile = [Cart serializeCart];
//Now send the xml file to the server
NSURL *url = [[NSURL alloc] initWithString:#"http://www.XXXXXXXXX.com/iOS_Files/xmlFile"];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:url];
[req setHTTPMethod:#"POST"];
NSData *paramData = [xmlFile dataUsingEncoding:NSUTF8StringEncoding];
[req setHTTPBody:paramData];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(theConnection)
{
NSMutableData *data = [[NSMutableData alloc] init];
self.receivedData = data;
[data release];
}
else
{
NSLog(#"Unable to make connection!");
}
I would really appreciate any help.
Thanks
See the class reference, there you can also find the links for the sample applications.
That code
if(theConnection)
{
NSMutableData *data = [[NSMutableData alloc] init];
self.receivedData = data;
[data release];
}
does not start the connection. The receivedData property will have a new NSData object, which is then changed as the response data received.
For the better understanding of the NSUrlConnection usage follow that official guide
What you can do else is to test the server w/o the application using REST Client firefox extension (just send the post request with it and see what happens).
One possible problem with the above code (their may be others also), is that the connection setup will be asynchronous. This is why you had to supply a delegate object above. Therefore, the connection is not actually made until the delegate gets a callback to say it is ready.
Have you implemented any delegate methods?

UIWebView doesn't load some link

hello
I'm trying to write an rss feed viewer for my iPhone. In my DetailView I have a UIWebView where I want to display specific link retrieved with the rss item.:
NSString* url = [data objectForKey:#"link"];
NSString *encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding ];
NSLog(#"Selected link:%#",url);
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:encodedUrl]];
[itemWebpage loadRequest:request];
[request release];
now,if the retrieved link is something like
www.shazaam.com
it works. But as soon as the link is something like:
http://www.shazam.com/music/web/track?id=41970148"
it doesn't. I suppose it's because of the parameter...but how can I fix the problem????
thanks a lot!
elos
stringByAddingPercentEscapesUsingEncoding: is for when you want to put a string into a query variable. You don't need to do it for entire URLs. The question mark is being encoded when it shouldn't be, so you are getting a 404. Don't encode the URL and you should be fine.