Wednesday, March 28, 2007

Hide form tag, but leave content

I often run into an issue in ASP.NET when I want to include a <form> on a page that posts to a 3rd party website. For example, I could have a PayPal button that posts directly to PayPal (as opposed to doing a "post-back") to the current page.

The problem is that a common practice in ASP.NET is to have a <form runat="server"> tag "high up" in the HTML, usually in the Master page. HTML doesn't allow overlapping <form> tags, so my PayPal button won't work. Since the higher level <form> is in the Master page, it makes removing it pretty messy. As far as I know, there's no built-in "hide this tag, but render the tag's contents" feature for controls. In the past I've maintained two master pages: the normal one and a "no form" version, but I've since discovered a more elegant solution.

I created a class called GhostForm that has a property RenderFormTag. When RenderFormTag is set to false, it doesn't render the <form> tag or closing tag, but does render all of the contents. This works perfectly so I can have my <form runat="server"> high up for most pages, but I can fine-tune it when I need forms posting to other sites or multiple forms.

Here's the code for GhostForm:
using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;

/// <summary>
/// This is a special form that can _not_ render the actual form tag, but always render the contents
/// </summary>
public class GhostForm : System.Web.UI.HtmlControls.HtmlForm
{
  protected bool _render;

  public bool RenderFormTag
  {
      get { return _render; }
      set { _render = value; }
  }

  public GhostForm()
  {
      //By default, show the form tag
      _render = true;
  }

  protected override void RenderBeginTag(HtmlTextWriter writer)
  {
      //Only render the tag when _render is set to true
      if (_render)
          base.RenderBeginTag(writer);
  }

  protected override void RenderEndTag(HtmlTextWriter writer)
  {
      //Only render the tag when _render is set to true
      if (_render)
          base.RenderEndTag(writer);
  }
}