Here's an interesting aspect of page validation I came to realize just recently.
Adding Validator Declaratively
Suppose we have a text box, a required field validator, a validation summary and a submit button. Nothing crazy here.
<asp:ValidationSummary runat="server" />
<asp:TextBox ID="Name" runat="server" />
<asp:CustomValidator
runat="server"
ErrorMessage="Enter name"
OnServerValidate="cv_ServerValidate"
Display="None" />
<asp:Button ID="Submit" runat="server" Text="Submit" />
The CustomValidator
control here is added to the control tree early in the page life cycle. When the control is initialized, it adds itself to the Page.Validators collection:
protected internal override void OnInit(EventArgs e)
{
base.OnInit(e);
this.Page.Validators.Add(this);
}
The server-side validation method is very simple:
protected void cv_ServerValidate (
object source,
ServerValidateEventArgs args)
{
args.IsValid = (Name.Text.Trim().Length > 0);
}
Adding Validator Dynamically
What if we cannot add a validator declaratively and therefore have to create and add it dynamically? The Page
class has a publicly available collection Validators
which seems to be a good fit.
protected override void OnInitComplete (EventArgs e)
{
base.OnInitComplete (e);
CustomValidator cv = new CustomValidator();
cv.ServerValidate +=
new ServerValidateEventHandler (cv_ServerValidate);
cv.Display = ValidatorDisplay.None;
cv.ErrorMessage = "Enter name";
Page.Validators.Add (cv);
}
Note the last line above. If you happen to also specify a JavaScript function to call upon validation on the client, it won't fire. For that matter, this validator won't render any HTML at all!
This actually did happen. We bought a suite of controls from a major vendor. Their souped-up combo box control didn't offer any validation, so I decided to subclass it and tack on a custom validator. This way I could do some validation both on the client and the server… except that my custom validator failed to render any HTML, although its server-side validation logic worked! This really had me scratching my head. If a validator control adds itself to the Page.Validators
collection, why can't I do it myself?
Reflector revealed that Page.Validators
is simply a wrapper around an ArrayList
with no special logic. And then it dawned on me:
My custom validator wasn't in the control tree, which is why it didn't go through the normal control life cycle and therefore had no render phase. Basically, I was adding it to an ArrayList
maintained by the Page
class, but it was never added to the control tree.
Conclusion
From this saga I learned that you shouldn't touch Page.Validators
unless you're developing your own validator control. If you absolutely need to create a validator on the fly, make sure you add it to page controls one way or another.