Click here to Skip to main content
15,867,453 members
Articles / Web Development / HTML
Article

Extending ASP.NET Web Controls With Custom HTML Attributes

Rate me:
Please Sign up or sign in to vote.
4.83/5 (37 votes)
13 Apr 20054 min read 234.5K   2.1K   115   26
Use existing functionality in ASP.NET to extend the framework's web controls.

Sample Image - main.jpg

Introduction

Have you ever written code to implement custom functionality, (text formatting, permission checks, etc.), to existing ASP.NET controls?  You can achieve such customizations by implementing custom web controls, but wouldn't it be nice to apply extra attributes to existing ASP.NET controls to achieve the same result?  This article covers a way you can use existing functionality in ASP.NET to extend existing web controls by applying your own custom HTML attributes. 

A Quick Background

To understand this extended functionality, one must be familiar with the ASP.NET life-cycle, particularly the way a System.Web.UI.Page creates its child controls.  If you look Page's object hierarchy, you can see that it directly inherits from the System.Web.UI.TemplateControl, which in terms inherits from the System.Web.UI.Control. The Control class defines the protected, and virtual, CreateChildControls method, a method used to notify server controls to create any contained child controls in preparation for posting back or rendering.  To implement our own version of this method, we need to create our own class that inherits from System.Web.UI.Page.

Creating A Simple Custom Page

To implement a simple base ASP.NET page, define a new class that inherits from System.Web.UI.Page.

public class BasePage : System.Web.UI.Page { ... }

Next we need to override the CreateChildControls method to specify our own control creation logic.

protected override void CreateChildControls() { ... }

Since all web and user controls must reside in a HTML form in order to work, we need to do two things:

  1. Within CreateChildControls, iterate through all 'page' controls and find the control of type System.Web.UI.HtmlControls.HtmlForm
  2. Iterate through the controls within the form control and select all controls of type System.Web.UI.WebControls.WebControl

The following code defines this discovery process:

/// <summary>
/// Overrides the common functionality for the creation
/// of controls within the page.
/// </summary>
protected override void CreateChildControls()
{
    // Find the form control in which all asp.net (or custom) controls
    // must be hosted.
    foreach (Control c in this.Controls)
    {
        if (c is System.Web.UI.HtmlControls.HtmlForm)
        {
            ProcessForm(c as HtmlForm);
        }
    }

    // Call the base implementation
    base.CreateChildControls();
}

/// <summary>
/// Process each of the controls within the form
/// </summary>
/// <param name="form">The html form for the page</param>
private void ProcessForm(HtmlForm form)
{
    // Find all the web controls, ie <asp:control_name />, and
    // check process them.
    //
    // You can also add logic here to check for user controls or 
    // custom user controls.
    foreach (Control cc in form.Controls)
    {
        if (cc is WebControl)
        {
            // Once you find the a web control, process any 
            // custom attributes you have specified.
            AttributeParser.ProcessControl(cc as WebControl);
        }
    }
}

Now that we have our base page and we've defined a discovery process, we can start the handling of our custom attributes with the help of some extra classes.

Stepping Through The Code

The main class for discovering custom HTML attributes is the AttributeParser class. This class contains a method called ProcessWebControl that simply iterates through all the previously defined attributes, represented by the AttributeType enumeration, and checks each web control's attributes for a match. If a match is found, the AttributeType is used in conjunction with the AttributeFactory class to get an instance of a class that implements the IAttribute interface. Using this class instance we then call the IAttribute.Apply method and pass the value of the attribute along with the control on which the attribute is defined in. This will allow the implementing class to perform any custom actions on the web control based on the value of the custom HTML attribute.

Here's a quick look at the code:

/// <summary>
/// Processes the control's custom attributes.
/// </summary>
/// <param name="control">Current web control being rendered.</param>
public static void ProcessControl(WebControl control)
{
    foreach(string attribute in Attributes)
    {
        // Get the value of the custom attributes
        string attributeValue = control.Attributes[attribute];

        // If the custom attribute is defined, process it
        if (attributeValue != null)
        {
            // Get the attribute's type
            AttributeType at = (AttributeType)Enum.Parse(typeof(AttributeType), 
                                attribute, true);

            // Get the class to process the custom attribute
            IAttribute customAttribute = AttributeFactory.GetAttribute(at);

            if (customAttribute != null)
            {
                // Apply the attribute for the control
                customAttribute.Apply(attributeValue, control);
            }
        }
    }
}

Two classes that implement the IAttribute interface are the PermissionAttribute class and the TextStyleAttribute class. The PermissionAttribute class is used to apply declarative security on the web control that contains the permission HTML attribute. In other words, if a TextBox controls defines the permission attribute in its HTML, then the TextBox will be enabled for the list of roles defined otherwise the control will be disabled.

<asp:textbox id="txtData" runat="server" permission="Administrators">INFO</asp:textbox>

Here's what the TextBox will look if the HttpContext.User is not part of Administrator role.

Disabled textbox using the permission custom HTML attribute

The TextStyleAttribute class is used to apply a custom look and feel to a TextBox web control.  For this article I've implemented the phone style that formats your text as a phone number as you type it with the aid of JavaScript. To enable this custom style, you need to apply the textstyle custom HTML attribute to your text box.

<asp:textbox id="txtPhone" runat="server" textstyle="phone" />

This TextBox will automatically add the '-' between the area code-prefix-postfix as you type in a number into the TextBox.

Applies custom javascript aid the formatting of the entered phone number.

The TextStyleAttribute class is implemented a little bit different from the PermissionAttribute class in the sense that it uses the value of the custom attribute to further define custom actions within the custom HTML attribute.  This allows you to implement different styles for the TextBox.  For example, you can define a date textstyle that automatically formats the numbers entered as a simple date (mm/dd/yyyy).  The TextStyleAttribute class is implemented as follows:

/// <summary>
/// Summary description for TextStyleAttribute.
/// 
/// Contains the custom implementation for processing the style type
/// for a System.Web.UI.WebControls.TextBox.
/// </summary>
public class TextStyleAttribute : IAttribute
{
    #region IAttribute Members

    /// <summary>
    /// Applies the specified style to the web control.
    /// </summary>
    /// <param name="attributeValue">The style used for the rendered control</param>
    /// <param name="wc">The current control</param>
    public void Apply(string attributeValue, WebControl wc)
    {
        // Perform only if the control is a text box
        if (wc is TextBox)
        {
            // Get the style to apply for the text box
            TextStyle mode = (TextStyle)Enum.Parse(typeof(TextStyle), 
                            attributeValue, true);

            // Apply the specific style
            switch(mode)
            {
                case TextStyle.Phone:
                    PhoneStyle(wc as TextBox);
                    break;
                
                // Add more styles here.
            }
        }
    }

    #endregion

    /// <summary>
    /// Applies the 'Phone' style to the text box (ddd-ddd-dddd)
    /// </summary>
    /// <param name="text">Current TextBox control</param>
    private void PhoneStyle(TextBox text)
    {
        // Add custom javascript
        text.Attributes.Add("onKeyUp", "javascript:AutoPhone(this)");
        
        // Set the max size for a phone number
        text.MaxLength = 12;
    }
}

For more information on the classes used, see the attached source.

Conclusion

The two presented attribute implementations are intended to show you how easy it is to extend the current controls bundled with ASP.NET and to give you a head start for creating your own custom HTML attributes.  If you currently have a custom ASP.NET framework adding this type of functionality will make your framework a bit more customizable.

Please feel free to leave any comments below.

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


Written By
Web Developer
United States United States
Javier is a consultant specializing in ASP.NET, system architecture, and training. He's also a MCSD .NET and a co-founder of the Iowa DotNET Users Group. Recently, Javier was awarded the Visual Developer ASP.NET MVP award from Microsoft.

On his blog you can find posts on ASP.NET, architecture, design patterns, XML and just recently, Indigo. Javier enjoys giving back to the community by speaking at user groups, local/regional .NET events, being active in forums and by writing articles for Code Project.

In his spare time, Javier enjoys spending time with his wife, newborn son, two golden retrievers and writing about himself in third person.

Click here to read Javier's blog.

Comments and Discussions

 
GeneralGreat Article Pin
KarthikNaresh6-May-14 2:06
KarthikNaresh6-May-14 2:06 
GeneralApplying to Controls in a Placeholder, on a Masterpages' Content Page Pin
Fergal Breen5-Feb-09 1:20
Fergal Breen5-Feb-09 1:20 
QuestionGetting Visual Studio to Recognize Custom Attributes? Pin
impostal2210-Oct-07 7:58
impostal2210-Oct-07 7:58 
GeneralApplying to a MAsterpage Pin
jhorlock11-Jun-07 6:20
jhorlock11-Jun-07 6:20 
GeneralRe: Applying to a MAsterpage Pin
Javier Lozano11-Jun-07 6:38
Javier Lozano11-Jun-07 6:38 
GeneralRe: Applying to a MAsterpage Pin
jhorlock12-Jun-07 0:39
jhorlock12-Jun-07 0:39 
GeneralBest article ever Pin
BoredOfCoding29-Mar-07 8:43
BoredOfCoding29-Mar-07 8:43 
GeneralRe: Best article ever Pin
Javier Lozano11-Jun-07 6:37
Javier Lozano11-Jun-07 6:37 
GeneralGreat One... Pin
Russell Aboobacker19-Dec-06 19:41
Russell Aboobacker19-Dec-06 19:41 
QuestionWhy not set the attribute to the control directly? Pin
yizhinantian9-Nov-06 22:53
yizhinantian9-Nov-06 22:53 
AnswerRe: Why not set the attribute to the control directly? Pin
Javier Lozano14-Nov-06 12:52
Javier Lozano14-Nov-06 12:52 
This is correct, the OnClick, Color, Text, etc. attributes can be set on a control and a Page (since a Page is a control). However, these are built-in to the control definition. What this article shows you is how you can attach your own attributes to the already defined controls without changing their implementation.

Does that make sense?

~Javier Lozano
Microsoft MVP - ASP.NET

QuestionInteresting article. Can this be done in VB? Pin
conacher30-Oct-06 6:07
conacher30-Oct-06 6:07 
AnswerRe: Interesting article. Can this be done in VB? Pin
Javier Lozano14-Nov-06 12:50
Javier Lozano14-Nov-06 12:50 
GeneralOverriding the incorrect method Pin
RayLouw4-Apr-06 5:23
RayLouw4-Apr-06 5:23 
GeneralRe: Overriding the incorrect method Pin
Javier Lozano4-Apr-06 15:10
Javier Lozano4-Apr-06 15:10 
GeneralRe: Overriding the incorrect method Pin
RayLouw4-Apr-06 21:10
RayLouw4-Apr-06 21:10 
GeneralRe: Overriding the incorrect method Pin
Javier Lozano7-Apr-06 13:51
Javier Lozano7-Apr-06 13:51 
QuestionHow would I add OPTGROUP to a Listbox Pin
Blogdar22-Jun-05 4:41
professionalBlogdar22-Jun-05 4:41 
AnswerRe: How would I add OPTGROUP to a Listbox Pin
Javier Lozano22-Jun-05 5:26
Javier Lozano22-Jun-05 5:26 
Questionwhy not inheritance? Pin
lunky13-Apr-05 17:33
lunky13-Apr-05 17:33 
AnswerRe: why not inheritance? Pin
Javier Lozano13-Apr-05 18:17
Javier Lozano13-Apr-05 18:17 
GeneralRe: why not inheritance? Pin
Stefaan Rillaert4-May-05 0:55
Stefaan Rillaert4-May-05 0:55 
GeneralGood article Pin
Heath Stewart13-Apr-05 5:22
protectorHeath Stewart13-Apr-05 5:22 
GeneralNice Article Pin
Anonymous13-Apr-05 4:41
Anonymous13-Apr-05 4:41 
Generaltoo ... Pin
powerpo9-May-05 17:04
powerpo9-May-05 17:04 

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

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