Click here to Skip to main content
Click here to Skip to main content

Implementing Non-ASP.NET Posts in ASP.NET

, 1 May 2009
Rate this:
Please Sign up or sign in to vote.
How to include multiple form tags in an ASP.NET page.

When interfacing with some resources on the Web, you are sometimes provided with a little snippet of HTML code. For example, to insert a PayPal button on your Website, PayPal provides HTML code that may look something like this.

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">

  <input type="hidden" name="cmd" value="_xclick">
  <input type="hidden" name="business" value="bob@domain.com">


  <input type="hidden" name="lc" value="US">
  <input type="hidden" name="item_name" value="Widget">


  <input type="hidden" name="amount" value="100.00">
  <input type="hidden" name="currency_code" value="USD">


  <input type="hidden" name="bn"
    value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest">


  <input type="image"
    src="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
    border="0" name="submit" alt="">

  <img alt="" border="0"
    src="https://www.paypal.com/en_US/i/scr/pixel.gif" 
    width="1" height="1">

</form>

HTML code to insert PayPal button

This snippet defines a <form> and several <input> tags, including a submit button. When the submit button is clicked, the items in the form are posted to the URL specified in the action attribute of the <form> tag. The target URL can then inspect the values of those <input> tags and perform the required operation.

However, you may find that such snippets don’t work correctly when inserted into an ASP.NET page. The main problem is that ASP.NET pages already define a form. In order for ASP.NET’s post-back mechanism to work, all the controls are placed within a <form> tag. Since HTML doesn’t allow nested <form> tags, inserting code like that shown above into an ASP.NET page causes problems.

There are a number of possible approaches to resolving this. Let me start with a couple that I think are less than ideal. The first approach is to simply move the inserted HTML code after the ending </form> tag of the ASP.NET form. Although you cannot nest <form> tags, it is okay to include multiple, non-nested <form> tags on the same page.

The result of this is that the page now has two separate <form> tags, and you’ll find this generally works as expected. However, the problem here is that you lose some ASP.NET functionality. For example, the inserted HTML code comes after your ASP.NET form, and so it is not really embedded within your ASP.NET content. And, if you are using master pages, you cannot do this in content pages because everything in a content page is placed inside of the <form> tag defined in the master page.

The second approach is kind of an ugly hack, and is shown below:

protected void btnPayPal_Click(object sender, ImageClickEventArgs e)
{
    System.Web.HttpContext.Current.Response.Clear();

    System.Web.HttpContext.Current.Response.Write("<html><head>");
    System.Web.HttpContext.Current.Response.Write("</head><body " + 
       "onload='document.form1.submit()'>");
    System.Web.HttpContext.Current.Response.Write("<form " + 
       "action='https://www.paypal.com/cgi-bin/webscr' " +
       "name='form1' method='post'>");

    System.Web.HttpContext.Current.Response.Write("<input " + 
       "type='hidden' name='cmd' value='_xclick'>");

   System.Web.HttpContext.Current.Response.Write(
       "<input type='hidden' name='business' " +
       "value='bob@domain.com'>");

   System.Web.HttpContext.Current.Response.Write(
       "<input type='hidden' name='lc' value='US'>");
   System.Web.HttpContext.Current.Response.Write(
       "<input type='hidden' name='item_name' value='Widget'>");
   System.Web.HttpContext.Current.Response.Write(
       "<input type='hidden' name='amount' value='100.00'>");
   System.Web.HttpContext.Current.Response.Write(
       "<input type='hidden' name='currency_code' value='USD'>
   System.Web.HttpContext.Current.Response.Write(
       "<input type='hidden' name='bn' " +
       "value='PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest'>

   System.Web.HttpContext.Current.Response.Write(
       "<input type='image' " +
       "src='https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif' " +
       "border='0' name='submit' alt=''>");

   System.Web.HttpContext.Current.Response.Write("<img alt='' border='0' " +
       "src='https://www.paypal.com/en_US/i/scr/pixel.gif' " +
       "width='1' height='1'>");

   System.Web.HttpContext.Current.Response.Write("</form>");
   System.Web.HttpContext.Current.Response.Write("</body></html>");

   System.Web.HttpContext.Current.Response.End();
}

Ugly hack to perform non-ASP.NET postback

This code runs in response to the user clicking a button named btnPayPal. It dynamically creates an HTML page and then serves it to the user’s browser. The page created duplicates the form in our first listing, but adds an onload attribute to the page’s <body> tag that causes the form to be submitted as soon as it loads, and the user never sees this temporary page.

This is definitely an ugly hack. And, while it works, it has some problems. The main problem is if, after running the code, the user presses the Back button in their browser, the browser will reload this temporary page, which will cause the same action to happen again, which definitely has the potential to cause some nasty problems.

After exploring both of these options, I finally settled on a third approach that seems more straightforward and doesn’t seem to have any major problems. Beginning with ASP.NET 2.0, buttons have a property called PostBackUrl, which can be used to have that button post back to a page other than the page that contains the button.

At first glance, this didn’t seem helpful. ASP.NET buttons are designed to post back to ASP.NET pages. And, I wanted to post back to a non-ASP.NET page. However, the post-back mechanism is the same in both cases. If we post back to a non-ASP.NET page, we’re going to send a lot of additional data—all of the form items on our ASP.NET form—to the target page. But, as long as their is no conflicting item names, which is unlikely, this really isn’t a problem.

Armed with this knowledge then, we can rewrite our original code block and insert it into an ASP.NET page.

<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="bob@domain.com">
<input type="hidden" name="lc" value="US">

<input type="hidden" name="item_name" value="Widget">
<input type="hidden" name="amount" value="100.00">

<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn"
       value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest">
<asp:ImageButton ID="ImageButton1" runat="server"
   ImageUrl="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif"
   PostBackUrl="https://www.paypal.com/cgi-bin/webscr" />

PayPal button inserted into ASP.NET page

I’ve removed the <form> tag from this code. We don’t need it since our ASP.NET form already defines a <form> tag. I’ve removed the <img> and submit <input> tags, and I’ve replaced them with an ImageButton. I set the ImageButton’s ImageUrl property to the same PayPal button image used in the original code and, finally, I set the PostBackUrl property to the URL specified in the action attribute of the <form> tag in our original HTML code.

The result is that, when the ImageButton is clicked, the entire form is posted to the PayPal URL. As I mentioned before, this includes all our other ASP.NET values, including the page’s ViewState data. But, the ViewState data is encrypted, and the PayPal site will only look at those values it is interested in.

The result is that I am able to insert a PayPal button at any location within my ASP.NET form, I’m still able to make use of all ASP.NET features, PayPal gets all the values it needs to do its job, and there is no funny business if the user happens to hit the browser’s Back button from the PayPal site.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jonathan Wood
Black Belt Coder
United States United States
Jonathan Wood has been a software developer for more years than he cares to admit. His current focus is on using C# and ASP.NET MVC to develop website applications, and C++ and MFC to develop desktop applications. His consulting company, SoftCircuits, is known for producing various commercial and shareware products.
 
Having an entrepreneurial spirit, Jonathan also has a number of other online businesses that he built from scratch such as Black Belt Coder, Trail Calendar and others. He also has expertise in designing brands (including graphics and logos) and search-engine optimization (SEO).
 
Jonathan is always willing to discuss consulting work or joint ventures with people looking to develop software or online businesses.
Follow on   Twitter

Comments and Discussions

 
SuggestionI think I've found a better way if you need to pull a bunch of items from a cart [modified] PinmemberMember 863094814-Mar-12 0:58 
GeneralThanks for this simple yet elegant solution PinmemberRay Wampler23-Mar-10 18:19 
GeneralAdd amount dynamically PinmemberMohan Patil22-Nov-09 20:09 
GeneralPure Genious!!! Pinmemberchris1758-Jul-09 11:31 
Man this is exactly what I have been looking for!!! Thanks a lot!!!!
 
Chris

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 1 May 2009
Article Copyright 2009 by Jonathan Wood
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid