Click here to Skip to main content
15,867,308 members
Articles / Web Development / ASP.NET
Article

Self Validating ASP.NET Text Box

Rate me:
Please Sign up or sign in to vote.
4.69/5 (46 votes)
6 Oct 20034 min read 216.4K   3.1K   95   16
How to extend web form controls to be self validating so you don't have to mess with validation controls.

Introduction

With the richness of .NET, I want more. I want web form controls in ASP.NET that have built in validation -- no messing with all the validation controls! You should be able to just create an IntegerTextBox or a MoneyTextBox, etc. and specify that it won't accept being blank or that it has a value within a range, etc. Plus, it should return the value in the right format so I don't have to mess with it. I would even like it to change colors when there is an issue.

So, I have struggled to figure out how to do this so you won't have to.

Implementing the IValidator interface

I delved into the SDK documentation and discovered that any control can be a page validator if it implements the IValidator interface. Here is a simple example derived from TextBox.

C#
using System;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace MyValidatingControls {
   public class TextBox : System.Web.UI.WebControls.TextBox, IValidator {
      private bool _valid = true;
      private string _errorMessage = "";

      public bool IsValid {
         get { return _valid; }
         set { _valid = value; }
      }

      public string ErrorMessage {
         get { return _errorMessage; }
         set { _errorMessage = value; }
      }

      public void Validate() {
      }
   }
}

Of course this doesn't do anything, but the code above fulfills the basic IValidator contract (i.e. it will compile). I created two private fields to hold the state and the error message, if there is one. To ensure our validator is executed, we have to add our validator to the list of page validators for the containing page.

I did a little homework reading the SDK and it mentions that validators add themselves to the list during initialization. IValidators basically register themselves. So, we override OnInit and OnUnload to add and remove our validator from the page's Validators list.

C#
protected override void OnInit(EventArgs e) {
   base.OnInit(e);
   Page.Validators.Add(this);
}

protected override void OnUnload(EventArgs e) {
   if (Page != null) {
      Page.Validators.Remove(this);
   }
   base.OnUnload(e);
}

Finishing the "Setup"

Before we can write our validator, I want to setup a few more helper items that will make things a little neater. I don't want to have to provide error messages based on each one of the validation issues. I will program those into the control, based on what type of data it should expect. Therefore, I need to provide a little more information to the control so that it can properly give error messages.

I will add a property called FriendlyName which will be used in all error messages to refer back to this control. So, if the control we are asking for has an ID of RetailPrice we make our FriendlyName be Retail Price or whatever it is labeled on the page.

C#
private string _friendlyName = "";

public string FriendlyName {
   get { return _friendlyName; }
   set { _friendlyName = value; }
}

Last, before we write our validation, I want to update IsValid to change my control to a light red color if it is invalid.

C#
public bool IsValid {
   get { return _valid; }
   set { 
      _valid = value; 
      if (!_valid) {
         this.BackColor = Color.LightCoral;
      } 
      else {
         this.BackColor = Color.White;
      }
   }
}

No blanks allowed

For our first validation, lets make it optional that the text field won't accept blanks. We need to make a property that can be set to "enable" this validation.

C#
private bool _blankAllowed = true;

public bool AllowBlank {
    get { return _blankAllowed; }
    set { _blankAllowed = value; }
}

Finally, we can write the Validation function and place it on a web page.

C#
public virtual void Validate() {
   this.IsValid = true;

   if (!this.AllowBlank) {
      bool isBlank = (this.Text.Trim() == "");

      if (isBlank) {
         this.ErrorMessage = 
             String.Format("'{0}' cannot be blank.", 
             this.FriendlyName);
         this.IsValid = false;
      }
   }
}

Expanding on the idea

Now that we have a basic text field with built-in validation, we can expand on the idea and create more interesting validating text box controls.

The next simple expansion on the idea would be an IntegerTextBox. I want my IntegerTextBox to set the range of valid values, but still we can allow for blanks. So, like before, we add the needed properties.

Since we built the basic TextBox, we only need derive from it and override the Validate and add new properties and we are in business.

C#
private int _minValue = Int32.MinValue;
private int _maxValue = Int32.MaxValue;

public int MinValue {
   get { return _minValue; }
   set { 
      _minValue = value; 
      
      if (_minValue > _maxValue) {
          int swap = _minValue;
          _minValue = _maxValue;
          _maxValue = swap;
      }
   }
}

public int MaxValue {
   get { return _maxValue; }
   set { 
      _maxValue = value; 
      
      if (_minValue > _maxValue) {
          int swap = _minValue;
          _minValue = _maxValue;
          _maxValue = swap;
      }
   }
}

Then, we update our Validate method and add a native value output.

C#
public override void Validate() {
   this.IsValid = true;

   bool isBlank = (this.Text.Trim() == "");

   if (isBlank) { 
      if (!AllowBlank) {
         this.ErrorMessage = String.Format("'{0}' " +
            "cannot be blank.", this.FriendlyName);
         this.IsValid = false;
      }
   } else {
      try {
         _value = Int32.Parse(this.Text);
         if (_value < this.MinValue) {
            this.ErrorMessage = String.Format("'{0}' cannot " +
              "be less than {1}", 
              this.FriendlyName, this.MinValue);
            this.IsValid = false;
         }
         
         if (_value > this.MaxValue) {
            this.ErrorMessage = String.Format("'{0}' " +
               "cannot be more than {1}", 
               this.FriendlyName, this.MinValue);
            this.IsValid = false;
         }
      } catch {
         this.ErrorMessage = String.Format("'{0}' " +
              "is not a valid integer.", this.FriendlyName);
         this.IsValid = false;
      }
   }
}

public int Value {
   get { return _value; }
   set { 
      _value = value;
      this.Text = _value.ToString();
   }
}

Conclusion

That's about it! Just extend on this class and you can create a DateTextBox or a CurrencyTextBox all with built-in validation. I have included a sample usage page that shows how nice it works.

Before we had:

HTML
<asp:TextBox id="Number" runat="server"/>
<asp:RequiredFieldValidator id="RequiredFieldValidator2" 
   ControlToValidate="Number" 
   Text="'Number' cannot be blank." runat="server"/>
<asp:RangeValidator id="Range1" ControlToValidate="Number" 
   MinimumValue="0" MaximumValue="100" 
   Type="Integer" Text="The value must be from 0 to 100!" 
   runat="server"/>

Now we have:

HTML
<MyControls:IntegerText id="Number" 
    FriendlyName="Number" MinValue="0" MaxValue="100" 
    AllowBlank="false" runat="server">

Mind you, my classes are far from finished nor does it provide the exact functionality as existing validation controls. One definite improvement would be to add client side scripting so that all validation doesn't happen on the server.

But, for someone like myself who doesn't use Visual Studio .NET, this can save a lot of typing and setting of properties.

I wanted everyone to see an example of how this is done, in case you are looking for the same kind of thing. Maybe in the future I will feel inspired enough to show you the completed set of classes I use to do this with.

History

I noticed in the SDK that adding the validator should occur in Init and not Load. So, I updated the text and code samples. I also added remove.

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
Just a plain-ole programmer. I work for NASA in Mission Planning Systems. I am most famous for the development of the J-Track satellite tracking software.

Comments and Discussions

 
QuestionVery Good article, yet there is a problem with validation groups due to a framework limitation Pin
Federico Di Marco29-Dec-16 12:29
Federico Di Marco29-Dec-16 12:29 
GeneralMy vote of 4 Pin
Amit kumar pathak15-Dec-11 7:16
Amit kumar pathak15-Dec-11 7:16 
QuestionTrouble using MyValidatingControls Assembly iin VS 2005 Pin
Mark Oliver29-Dec-06 11:11
Mark Oliver29-Dec-06 11:11 
QuestionHelp! I want it with no postback Pin
EdwinY5-Mar-06 14:05
EdwinY5-Mar-06 14:05 
AnswerRe: Help! I want it with no postback Pin
Christopher Stratmann2-Nov-06 14:15
Christopher Stratmann2-Nov-06 14:15 
GeneralText Box Pin
Anonymous23-Oct-05 23:42
Anonymous23-Oct-05 23:42 
Hi Guys. I think it is so simple for you but i coulnd't find anything. when someone presses enter in text box i want to redirect him to another page but i couldn't find anything about pressinig enter.
Thanks for helps
Generali have a problem in my app Pin
sshekhar_k28-Apr-04 23:37
sshekhar_k28-Apr-04 23:37 
QuestionHow can I extend to a datetime textbox? Pin
uydo15-Mar-04 12:46
uydo15-Mar-04 12:46 
QuestionGood idea, but why cannot see textboxes in designer?? Pin
Member 72627024-Nov-03 7:34
Member 72627024-Nov-03 7:34 
AnswerRe: Good idea, but why cannot see textboxes in designer?? Pin
Patrick Meyer15-Dec-03 15:19
Patrick Meyer15-Dec-03 15:19 
GeneralRe: Good idea, but why cannot see textboxes in designer?? Pin
sshekhar_k28-Apr-04 23:44
sshekhar_k28-Apr-04 23:44 
NewsRe: Good idea, but why cannot see textboxes in designer?? Pin
JC@Rio26-Sep-05 2:13
JC@Rio26-Sep-05 2:13 
QuestionHow do i add this to my app? Pin
RobEdwards19-Oct-03 15:45
RobEdwards19-Oct-03 15:45 
GeneralNice article Pin
Mike Ellison9-Oct-03 7:23
Mike Ellison9-Oct-03 7:23 
GeneralA nickle Pin
Paul Watson5-Oct-03 20:44
sitebuilderPaul Watson5-Oct-03 20:44 
GeneralGood Idea! Pin
J. Dunlap5-Oct-03 20:38
J. Dunlap5-Oct-03 20:38 

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.