
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:
- We want to perform a search on google.com with search criteria from an ASP.NET web page.
- 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.
protected override void RenderAttributes(System.Web.UI.HtmlTextWriter writer) {
writer.WriteAttribute("name", this.Name);
writer.WriteAttribute("method", this.Method);
writer.WriteAttribute("action", this.ResolveUrl(this.Action), true);
this.Attributes.Remove("name");
this.Attributes.Remove("method");
this.Attributes.Remove("action");
string submitEvent = this.Page_ClientOnSubmitEvent;
if (submitEvent != null && submitEvent.Length > 0) {
if (this.Attributes["onsubmit"] != null) {
submitEvent = submitEvent + this.Attributes["onsubmit"];
this.Attributes.Remove("onsubmit");
}
writer.WriteAttribute("language", "javascript");
writer.WriteAttribute("onsubmit", submitEvent);
}
writer.WriteAttribute("id", this.ClientID);
this.ViewState.Remove("innerhtml");
this.Attributes.Render(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; }
}
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.
- Extract all the files in the zip file to a folder say c:\deriveForm.
- 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.
- Make a folder named bin under C:\deriveform and copy DerivedTool.WebControls.HtmlForm.dll to this new folder.
- 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!