Building a Better Custom Validator

posted on 2005-01-05 at 00:12:09 by Joel Ross

I recently had a need to have a custom validator that would validate even when the textbox was empty. My first solution was to use a custom validator in conjunction with a required field validator. That worked just fine.

Until I found a situation where the field would sometimes be required and sometimes not be required. And it wasn't based on entries in another field. It had to do with whether a whole form was filled out - if nothing was populated, then the form is fine. If any one piece was populated, then it should validate everything.

So the custom / required validator combo didn't work for me. So I decided to build my own validator. It's very similar to the custom validator (I used that as my code sample using Reflector).

Here's the code for the validator:

     1: using System;
     2: using System.ComponentModel;
     3: using System.Security.Permissions;
     4: using System.Web;
     5: using System.Web.UI;
     6: using System.Web.UI.WebControls;
     7:  
     8: namespace RossCode.Web.UI.WebControls
     9: {
    10:     /// <summary>
    11:     /// Summary description for RequiredCustomValidator.
    12:     /// </summary>
    13:     [ToolboxData("<{0}:RequiredCustomValidator runat=server ErrorMessage=\"RequiredCustomValidator\"></{0}:RequiredCustomValidator>"), DefaultEvent("ServerValidate")]
    14:     public class RequiredCustomValidator : System.Web.UI.WebControls.BaseValidator
    15:     {
    16:         static RequiredCustomValidator() {
    17:             EventServerValidate = new object();
    18:         }
    19:  
    20:         public RequiredCustomValidator() { }
    21:  
    22:         protected override bool EvaluateIsValid() {
    23:             string textValue = "";
    24:             string controlId = base.ControlToValidate;
    25:  
    26:             if (controlId.Length > 0) {
    27:                 textValue = base.GetControlValidationValue(controlId);
    28:             }
    29:             
    30:             return OnServerValidate(textValue);
    31:         }
    32:  
    33:         public virtual bool OnServerValidate(string value){
    34:             ServerValidateEventHandler handler1 = (ServerValidateEventHandler) base.Events[RequiredCustomValidator.EventServerValidate];
    35:             ServerValidateEventArgs args1 = new ServerValidateEventArgs(value, true);
    36:             if (handler1 != null) {
    37:                 handler1(this, args1);
    38:                 return args1.IsValid;
    39:             }
    40:             return true;
    41:  
    42:         }
    43:  
    44:         private static readonly object EventServerValidate;
    45:  
    46:         public event ServerValidateEventHandler ServerValidate {
    47:             add {
    48:                 base.Events.AddHandler(RequiredCustomValidator.EventServerValidate, value);
    49:             }
    50:             remove {
    51:                 base.Events.RemoveHandler(RequiredCustomValidator.EventServerValidate, value);
    52:             }
    53:         }
    54:  
    55:         protected override bool ControlPropertiesValid() {
    56:             string controlId = base.ControlToValidate;
    57:             if (controlId.Length > 0) {
    58:                 base.CheckControlValidationProperty(controlId, "ControlToValidate");
    59:             }
    60:             return true;
    61:         }
    62:  
    63:         public string ClientValidationFunction {
    64:             get {
    65:                 object obj1 = this.ViewState["ClientValidationFunction"];
    66:                 if (obj1 != null) {
    67:                     return (string) obj1;
    68:                 }
    69:                 return string.Empty;
    70:             }
    71:             set {
    72:                 this.ViewState["ClientValidationFunction"] = value;
    73:             }
    74:         }
    75:  
    76:         protected override void AddAttributesToRender(HtmlTextWriter writer) {
    77:             base.AddAttributesToRender(writer);
    78:             if (base.RenderUplevel) {
    79:                 writer.AddAttribute("evaluationfunction", "RequiredCustomValidatorEvaluateIsValid");
    80:                 if (this.ClientValidationFunction.Length > 0) {
    81:                     writer.AddAttribute("clientvalidationfunction", this.ClientValidationFunction);
    82:                 }
    83:             }
    84:         }
    85:     }
    86: }

I'm not sure why, but for some reason, it doesn't work in design view. But if you know me or read this blog regularly, you'll know I don't much care for design view anyway. Even without it, this works.

The ServerValidate event fires even when nothing is in the box. I am now thinking about doing my own custom control for the regular expression validator too - when I give it a regex, and the regex doesn't allow blanks, why is that valid?

Anyway, here's the code. Feel free to use it as you please.

Categories: ASP.NET