home | blog | become an author | about us | contact us | link to us
Articles
By Column

angryCoder
Bits That Byte
Reviews
Nancy Ruthless
En "Code"
Advice
NET Income
Top 10
The Brutal Truth
Whatever
Cartoons
Email Court

Articles
By Author

become an author
ALL ARTICLES (297)
Jason Bock (16)
Nancy Carver Abbott (5)
Jonathan Goodyear (122)
Danny Lesandrini (8)
Clint Lewis (8)
Jason Mauss (9)
James McCutcheon (6)
Peter McMahon (5)
Brian Peek (10)
Jason Salas (8)
Eran Sandler (6)


En "Code" Email This Article | En "Code" column | Printable Version

Subclass .NET Server Controls To Add Validation



****NOTE: This article was written using Beta 1 of the .NET Framework. Therefore, some modifications may need to be made to the code to make it Beta 2 and/or RTM compliant.

It's Free Code Friday again! This week, I'm going to show you how to encapsulate your server control validation through subclassing. Pretty much everyone has heard of the new ASP.NET validation controls. While they are a neat concept, it's kind of a pain in the neck to create a validator control instance (possibly more than one) for each input element on a form. The .NET Framework allows you to subclass server controls, so why not use this to our advantage by rolling a form input element and its associated validation logic into one neat "reusable" package?

Setup
As usual, I will go through the code line by line in this section, and you can follow along by looking at the code example below. Although the example here is in C#, the downloadable source code contains both C# and VB.NET versions of the code.

We start off by defining our subclassed control. By looking at the class declaration, you'll notice that I have chosen to subclass the Label object. This is because a Label object acts as a transparent container for anything that I wish to put in it. Immediately inside the class definition, I define two private fields. The first, _errorMessage, holds the reference to the message that will be displayed beside the telephone number TextBox, should its validation fail. The second field defined here, _phoneNumber, is a reference to the actual TextBox object on the form where the user will enter their telephone number.

Next, I declare the PhoneBox object's constructor. All that I do in this routine is add the internal TextBox reference to the Controls collection of the PhoneBox object's base object (eg. our subclassed Label object). It is never a good idea to allow direct access to internal class fields, so the next thing that I do is declare a public property procedure named ErrorMessage to handle access to the internal _errorMessage field. Notice that I define a default value that is returned if the developer opts not to specify a custom error message to be displayed. Default values for property procedures make your code much more user friendly.

The real "meat" of the example takes place in the next code block. This is the Validate method. The first thing that has to be done is to strip out any unwanted characters that the user may have entered. This is done using the static Replace method of the Regex class. Note that you must import the System.Text.RegularExpressions namespace in order to use the Regex class. This removes all non-numeric characters from the text box and reassigns the "clean" version to the TextBox object. At this point I guess I should clarify that I am FAR from an expert on Regular Expressions. The ones that I use in this code example are only meant for demonstrative purposes. You'll probably want to add more thorough validation code if you want to put this code into a production environment. Getting back to the example, I now create a new object instance of the Regex class, feeding the Regular Expression pattern that I want to use into the class constructor. A simple call to the IsMatch method of my Regex object determines whether my TextBox contains 10 and only 10 numeric digits (this routine does not take non-US phone numbers into account).

If the IsMatch method does not return true, then the Regex object was unable to find a match with the Regular Expression pattern that I fed into it. This means that the user has entered an invalid phone number. If this is the case, then I first add a style attribute to the Label control that I subclassed in order to make the error message appear in red. Then, I actually display the error message by adding a LiteralControl to the subclassed Label object's Controls collection. That completes my PhoneBox class definition.

Implementation
In order to implement the PhoneBox control that I just created, I need to declare an instance of the PhoneBox class type that is accessible to all of the events on the page. I do this by declaring my PhoneBox object, pb, "outside" of any of the event handler declarations. Next, I have to add my PhoneBox object to the page. The best place to do this is in the Page_Init event handler. I create a new instance of the PhoneBox object, set its ErrorMessage property (which, as you remember, is optional), and call the Add method of the placeHolder Label's Controls collection. The placeHolder Label object does just what its name implies. It is just a container that I can use to add server controls at a specific place on the web form.

You'll notice further down in the code example that I have declared a Button server control. I have specified the the onclick event to be handled by the submit_onclick event handler, which is what I declare next in the code. The submit_onclick event handler consists of only one line of code. All I have to do is call the Validate method of my PhoneBox object instance, pb, and it takes care of itself. There is no need to mess with any of the ASP.NET validation controls.

In practice, I would have compiled my PhoneBox class into its own assembly (or combined several different custom input classes into one assembly namespace). That way, I would only need to import the namespace that contained my PhoneBox class any time I wanted to use it. It is easy to see the power and flexibility that this approach opens up to you. You can create an entire library of custom input controls specific to your project (or as general as you like) that has the validation logic baked right in. My name is Jonathan Goodyear, and I am the angryCoder.

Please take the time to add your feedback to this article by clicking the "Post your comments" link below the code example, or talk things over with others in either the angryCoder forums (which can be found in the menu bar to your left), or the angryCoder Listserv.

The Subclassed Server Control Code | Download source code (both VB and C# versions)
<%@ Page Language="c#" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>

<script language="c#" runat="server">
    private class PhoneBox : Label
    {
        private string _errorMessage;
        private TextBox _phoneNumber = new TextBox();

        public PhoneBox()
        {
            base.Controls.Add(_phoneNumber);
        }

        public string ErrorMessage
        {
            get
            {
                if(_errorMessage == null)
                &nb; sp;   {return "*";}
                else
                     {return _errorMessage;}
            }
            set {_errorMessage = value;}
        }

        public bool Validate()
        {
            bool valid;

            //clean out unwanted characters
            _phoneNumber.Text = Regex.Replace(_phoneNumber.Text,"[^0-9]","");

            //check to see if the phone number is valid
            Regex r = new Regex("^[0-9]{10}$");
            valid = r.IsMatch(_phoneNumber.Text);

            if(!valid)
            {
                base.Style.Add("color","red");
                base.Controls.Add(new LiteralControl(ErrorMessage));
            }
            return valid;
        }
    }

    //declare the PhoneBox object
    PhoneBox pb;

    protected void Page_Init(object sender, EventArgs e)
    {
        pb = new PhoneBox();
        pb.ErrorMessage = "* Invalid";
        placeHolder.Controls.Add(pb);
    }

    protected void submit_click(object sender, EventArgs e)
    {
        pb.Validate();
    }
</script>

<html>
<head>
<title>Subclassing Server Controls</title>
</head>
<body>
<form runat="server">
    Enter your phone number:<br />
    <asp:label id="placeHolder" runat="server" /><br />
    <asp:Button id="submit" Text="Click Me" onclick="submit_click" runat="server" />
</form>
</body>

Article Feedback View all comments | Post your comments

Jonathan, you are using a label control...  (Remas Wojciechowski3/9/2001 12:46:15 PM
...  (9/25/2001 3:20:34 PM
HI ALL !! Best my wishes !! Cool site ! ...  (Asert3/4/2006 2:45:31 AM
I love big butts, I just cant help mysel...  (Johny Ringo3/6/2006 4:03:41 PM
I love big butts, I just cant help mysel...  (Johny Ringo3/9/2006 1:58:37 PM
goseame@msn.com goseame@msn.com goseame@...  (goseame@msn.com4/5/2006 11:10:05 PM
Free Online Credit Score checker I fi...  (4/24/2006 10:31:18 PM