Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Go Beyond the limitations of ASP.NET Form

0.00/5 (No votes)
17 Mar 2004 1  
An article on the limitations of ASP.NET Form, especially the missing PostBack Action of a <form> element.

Sample image

Introduction

One of the most common hitches that ASP developers encounter when they first approach ASP.NET is that managed Web applications must be written according to a single-form interface model. In the single form interface model, each page always posts to itself by default using the POST HTTP method. The HTTP method and the target frame of the post can be programmatically adjusted using ad hoc form properties� Method and Target. The final destination of the postback can't be changed in any way. You can correlate the terminologies of a single-form interface to the single-document interface (SDI) and multiple-form interface to the multiple-document interface (MDI) in client server.

Following is the description found on MSDN regarding the limitation.

�The action attribute is always set to the URL of the page itself. The action attribute cannot be changed; therefore, you can only post back to the page itself.� (ref: Goto definition on MSDN).

This article is to illustrate the limitation of the ASP.NET Form control, which doesn�t provide the facility of submitting data to other pages or sites.

Let�s consider a situation where either:

  1. We want to perform a search on google.com with search criteria from an ASP.NET web page.
  2. Or we want to look at current stock quote of a Company listed on NASDAQ or NYSE by submitting information from an ASP.NET web page.

We cannot fulfill the above requisites in currently available UI related controls in ASP.NET.

This article is concentrating on the aspects of providing the Action property to a server-side form object based on the very own HtmlForm class itself which further can be extended to adopt multiple-form interface.

For live demo of this submission, navigate to Live Demo site.

Background (HtmlForm class: reviewed)

In HTML and ASP programming, the form element (i.e., <FORM>) features the Action property that programmers use to redirect to another URL after clicking. In ASP.NET, server-side forms are rendered using a class named HtmlForm under the System.Web.UI.HtmlControls namespace. This class doesn't provide the familiar Action property, nor does it supply an alternative property to perform the similar functionality. As a result, the single form interface model is so deep-rooted in ASP.NET that there's no way around it.

Before going into further detail, let's take a little review on HtmlForm. The HtmlForm class is derived from HtmlContainer class and implements the IAttributeAccessor interface. So, the base class (HtmlContainer) provides HtmlForm the ability to govern and contain child controls; IAttributeAccessor interface provides the ability to read and write the attributes of the opening tag (i.e., <FORM �..) itself. The HtmlForm class is not sealed and thus it is permissible for further inheritance as well as customization.

CHtmlForm: a more powerful shape of HtmlForm for ASP.NET

While we reviewed HtmlForm class, we found a starting point to think for providing Action property to it, because the HtmlForm class is not sealed and thus can be further inherited. As like other .NET controls, it also features a bunch of protected, overridable methods that you could exploit to customize the overall behavior. You can achieve this with the help of reflection. As we know, Reflection allows you to access any property on an object, even though the property is marked protected, internal, or private.

Let us start the process of customization of HtmlForm; CHtmlForm is an inherited class from HtmlForm class under the System.Web.UI.HtmlControls namespace. HtmlForm class provides 4 protected as well as public methods; one of them is the RenderAttributes method. The purpose of this method is to provide user defined implementation of the default rendering process. It has a parameter of the type HtmlTextWriter, to render final values of all attributes like Method, target, name, id, action to the parent object; for our case, it is the Page object.

The HtmlTextWriter object formulated a new Action attribute by resolving the hidden GetActionAttribute of HtmlForm object.

    /// <summary>

    /// purpose: Overridden to render custom Action attribute

    /// The main purpose of the Overridding is to grab the

    /// "action" attribute of the original 

    /// form

    /// </summary>

    protected override void RenderAttributes(System.Web.UI.HtmlTextWriter writer) {

            
        // Prepare our own action , method and name

        writer.WriteAttribute("name", this.Name);
        writer.WriteAttribute("method", this.Method);
        writer.WriteAttribute("action", this.ResolveUrl(this.Action), true);
        // Remove From HtmlForm, with changes to Action

        this.Attributes.Remove("name");
        this.Attributes.Remove("method");
        this.Attributes.Remove("action");
    
        string submitEvent = this.Page_ClientOnSubmitEvent;
        // Now check the onsubmit event associated with Htmlform 

        if (submitEvent != null && submitEvent.Length > 0) {
            // ok.. this for has a "OnSubmit" 

            if (this.Attributes["onsubmit"] != null) {
                submitEvent = submitEvent + this.Attributes["onsubmit"];
                this.Attributes.Remove("onsubmit");
            }
            //Add some new Attributes to make the new form little more rich

            writer.WriteAttribute("language", "javascript");
            writer.WriteAttribute("onsubmit", submitEvent);
        }
        writer.WriteAttribute("id", this.ClientID);

        // following is meant for HtmlContainerControl

        this.ViewState.Remove("innerhtml");
        // following is meant for HtmlControl

        this.Attributes.Render(writer);
    }
//   The above code shows the overriden method RenderAttribute(writer)
private Object GetHideProperty(Object target, 
          Type targetType, String propertyName ) 
{
    PropertyInfo property = targetType.GetProperty(propertyName, 
                            BindingFlags.IgnoreCase |
                            BindingFlags.Instance | BindingFlags.NonPublic );
    if ( property != null ) {return property.GetValue(target, null);}
    else {return null; }
}
    
/// The above code shows the GetHideProperty which uses reflection

/// to access any property on an object, even though the property

/// is marked protected, internal, or private.

Points of Interest

Following code snippet shows how the final structure of a page will look like:

<%@ Register TagPrefix="dtform" Namespace="DerivedTool.WebControls" 
                  Assembly="DerivedTool.WebControls.HtmlForm" %>
        
  <dtform:CHtmlForm Action="some_other_page.aspx" runat="server"> 
        <asp:TextBox id="symbols" runat="server" value=></asp:TextBox> 
        <asp:Button runat="server" Text="check Quote" /> 
  </dtform:CHtmlForm>

If you want to PostBack to the same ASP.NET page, just leave Action property as blank. For live demo of this submission, navigate to Live Demo site.

How to deploy CHtmlForm

Though deployment of this server�side control is very easy and simple, I am providing following steps to test the control with ASP.NET.

  1. Extract all the files in the zip file to a folder say c:\deriveForm.
  2. Make C:\deriveform as a virtual directory by giving name as �derivedemo�, if you have IIS server installed on your machine, other wise put the folder on a machine having IIS installed in it.
  3. Make a folder named bin under C:\deriveform and copy DerivedTool.WebControls.HtmlForm.dll to this new folder.
  4. Open your browser and navigate to http://localhost/derivedemo/derivedForm.aspx

    Or navigate to http://<SERVER>/derivedemo/derivedForm.aspx (if you don�t have IIS on the current machine).

Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here