13

For a GET request I've tried this simple method:

NSString *urlAddress = @"http://example.com/";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[uiWebViewThingy loadRequest:request];

(Although it doesn't seem to work if the request contains high UTF-8 characters. )

I want to send a POST from the iPhone.

This also give an overview for sending POST/GET requests although what I really want to do is embed the resulting web page into UIWebView. What would be the best way to go around that?

shim
  • 9,289
  • 12
  • 69
  • 108
Gazzer
  • 4,524
  • 10
  • 39
  • 49

7 Answers7

13

You can use an NSMutableURLRequest, set the HTTP method to POST, and then load it into your UIWebView using -loadRequest.

Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
  • This is what I tried (see the link in the OP) and I tried to use the connectionDidFinishLoading method to do something like [uiWebViewThing loadRequest:responseData] but it's the wrong kind of data. The response data is NSMutable but it needs to be NSUrlRequest - I must be doing something obvious wrong. – Gazzer Jan 04 '10 at 23:17
  • 1
    The code above uses an NSURLRequest. You need to use an NSMutableURLRequest. Don't mess around with connectionDidFinishLoading, just load it into the webView using -loadRequest. – Ben Gottlieb Jan 04 '10 at 23:51
10

Thanks for you answer Seva. I've made a method out of your code, hope this helps other people :)

//-------------------------------------------------------------------
//  UIWebViewWithPost
//       init a UIWebview With some post parameters
//-------------------------------------------------------------------
- (void)UIWebViewWithPost:(UIWebView *)uiWebView url:(NSString *)url params:(NSMutableArray *)params
{
    NSMutableString *s = [NSMutableString stringWithCapacity:0];
    [s appendString: [NSString stringWithFormat:@"<html><body onload=\"document.forms[0].submit()\">"
     "<form method=\"post\" action=\"%@\">", url]];
    if([params count] % 2 == 1) { NSLog(@"UIWebViewWithPost error: params don't seem right"); return; }
    for (int i=0; i < [params count] / 2; i++) {
        [s appendString: [NSString stringWithFormat:@"<input type=\"hidden\" name=\"%@\" value=\"%@\" >\n", [params objectAtIndex:i*2], [params objectAtIndex:(i*2)+1]]];
    }    
    [s appendString: @"</input></form></body></html>"];
    //NSLog(@"%@", s);
    [uiWebView loadHTMLString:s baseURL:nil];
}

to use it

NSMutableArray *webViewParams = [NSMutableArray arrayWithObjects:
                                 @"paramName1", @"paramValue1",
                                 @"paramName2", @"paramValue2",
                                 @"paramName3", @"paramValue3", 
                                 nil];
[self UIWebViewWithPost:self.webView url:@"http://www.yourdomain.com" params:webViewParams];
Louis de Decker
  • 525
  • 1
  • 7
  • 14
  • This solved my problem, Thanks a lot. I want to improve the answer, you can use Dictionary instead of Array to avoid missing key-value pair. Use this sample code : `for (NSString * key in params) { NSString * hiddenParam = [NSString stringWithFormat:@"\n", key, [params objectForKey:key]]; [s appendString: hiddenParam]; }` – krischu Apr 29 '15 at 09:41
5

(edited original answer to include newly tested code)

I just wanted to drop in my version of this request. I have used a dictionary to represent the post parameters.

It's a chunk of code but is simple enough to drop into a view with a webview and use for all URL loading. It will only POST if you send a "postDictionary". Otherwise it will use the url you sent it to just GET things.

- (void) loadWebView:(UIWebView *)theWebView withURLString:(NSString *)urlString andPostDictionaryOrNil:(NSDictionary *)postDictionary {
    NSURL *url                          = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request        = [NSMutableURLRequest requestWithURL:url
                                             cachePolicy:NSURLRequestReloadIgnoringCacheData
                                         timeoutInterval:60.0];


    // DATA TO POST
    if(postDictionary) {
        NSString *postString                = [self getFormDataString:postDictionary];
        NSData *postData                    = [postString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
        NSString *postLength                = [NSString stringWithFormat:@"%d", [postData length]];
        [request setHTTPMethod:@"POST"];
        [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
        [request setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:postData];
    }

    [theWebView loadRequest:request];
}
- (NSString *)getFormDataString:(NSDictionary*)dictionary {
    if( ! dictionary) {
        return nil;
    }
    NSArray* keys                               = [dictionary allKeys];
    NSMutableString* resultString               = [[NSMutableString alloc] init];
    for (int i = 0; i < [keys count]; i++)  {
        NSString *key                           = [NSString stringWithFormat:@"%@", [keys objectAtIndex: i]];
        NSString *value                         = [NSString stringWithFormat:@"%@", [dictionary valueForKey: [keys objectAtIndex: i]]];

        NSString *encodedKey                    = [self escapeString:key];
        NSString *encodedValue                  = [self escapeString:value];

        NSString *kvPair                        = [NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue];
        if(i > 0) {
            [resultString appendString:@"&"];
        }
        [resultString appendString:kvPair];
    }
    return resultString;
}
- (NSString *)escapeString:(NSString *)string {
    if(string == nil || [string isEqualToString:@""]) {
        return @"";
    }
    NSString *outString     = [NSString stringWithString:string];
    outString                   = [outString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    // BUG IN stringByAddingPercentEscapesUsingEncoding
    // WE NEED TO DO several OURSELVES
    outString                   = [self replace:outString lookFor:@"&" replaceWith:@"%26"];
    outString                   = [self replace:outString lookFor:@"?" replaceWith:@"%3F"];
    outString                   = [self replace:outString lookFor:@"=" replaceWith:@"%3D"];
    outString                   = [self replace:outString lookFor:@"+" replaceWith:@"%2B"];
    outString                   = [self replace:outString lookFor:@";" replaceWith:@"%3B"];

    return outString;
}
- (NSString *)replace:(NSString *)originalString lookFor:(NSString *)find replaceWith:(NSString *)replaceWith {
    if ( ! originalString || ! find) {
        return originalString;
    }

    if( ! replaceWith) {
        replaceWith                 = @"";
    }

    NSMutableString *mstring        = [NSMutableString stringWithString:originalString];
    NSRange wholeShebang            = NSMakeRange(0, [originalString length]);

    [mstring replaceOccurrencesOfString: find
                             withString: replaceWith
                                options: 0
                                  range: wholeShebang];

    return [NSString stringWithString: mstring];
}
bladnman
  • 2,591
  • 1
  • 25
  • 20
3

You can use something like ASIHTTPRequest to make the POST request (With the option of doing it asynchronously) and then load the response string/data into the UIWebView. Look at this page under the section titled Sending data with POST or PUT requests and then look at the Creating an asynchronous request section at the top for information on how to handle the response string/data.

Hope that helps, sorry if I misunderstood your question.

Jorge Israel Peña
  • 36,800
  • 16
  • 93
  • 123
2

Using loadHTMLString, feed a page to the UIWebView that has a hidden, pre-populated form, then make that page do a Javascript forms[0].submit() on loading.

EDIT: First, you collect the input into variables. Then you compose HTML like this:

NSMutableString *s = [NSMutableString stringWithCapacity:0];
[s appendString: @"<html><body onload=\"document.forms[0].submit()\">"
 "<form method=\"post\" action=\"http://someplace.com/\">"
 "<input type=\"hidden\" name=\"param1\">"];
[s appendString: Param1Value]; //It's your variable
[s appendString: @"</input></form></body></html>"];

Then you add it to the WebView:

[myWebView loadHTMLString:s baseURL:nil];

It will make the WebView load the form, then immediately submit it, thus executing a POST request to someplace.com (your URL will vary). The result will appear in the WebView.

The specifics of the form are up to you...

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • I don't really understand this. I'm trying to send a POST request from the iPhone based on a users input and have the server produce a page which in turn will appear inside the UIWebView. – Gazzer Jan 04 '10 at 22:47
  • This also true for `WKWebView` (iOS8). Because maybe there is bug and also `loadHTMLString` method works – Aznix Sep 25 '14 at 10:43
  • I have the same requirement like above, when I tried to load the HTML file in to WebView it's working fine. But when I tried to load the request to WebView it's not working. Any idea why it's not working? – Vinod Radhakrishnan Oct 21 '21 at 22:04
  • Sorry, you didn't provide enough information to debug this. Also, I've already answered Gazzer's question. Have you tried approaches from other answers here? If so, and none of those work, why won't you ask a question of your own? SO is not a discussion thread. – Seva Alekseyev Oct 21 '21 at 23:12
1

Create POST URLRequest and use it to fill webView

 NSURL *url = [NSURL URLWithString: @"http://your_url.com"];
 NSString *body = [NSString stringWithFormat: @"arg1=%@&arg2=%@", @"val1",@"val2"];
 NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
 [request setHTTPMethod: @"POST"];
 [request setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
 [webView loadRequest: request];
Dixit Patel
  • 205
  • 2
  • 16
1

Here is a Swift version of Seva Alekseyev's answer which worked perfectly for me. Thanks for the nice post mate! BTW following code is in Swift 3.1.

func injectPOST(params data: [String: Any]) {
    var str = String()
    str.append("<html><head></head>")
    str.append("<body onload=\"payment_form.submit()\">")
    str.append("<form id=\"payment_form\" action=\"\(urlString)\" method=\"post\">") //urlString is your server api string!

    for object in data { //Extracting the parameters for request
      str.append("<input name=\"\(object.key)\" type=\"hidden\" value=\"\(object.value)\">")
    }

    str.append("</form></body></html>")
    webView?.loadHTMLString(stringObj, baseURL: nil)
}
onCompletion
  • 6,500
  • 4
  • 28
  • 37