Schrödinger’s Validator

Checking Page Validator Controls Sans Error Display

ASP.NET Validator controls are a helpful mechanism for alerting our users that there is something wrong with their input. But what if we need to check the validity of fields on a web page without actually displaying the results to the user? I ran into just such a situation on a recent project, and my solution turned out to be useful enough to bring in for show and tell.

Code-Behind Page Validation 101

Our friend the Page class has a Validate() method that runs any validators present on the page, and an IsValid property that is set to false if any validators on the page have been violated. In the code, these would be used thusly:

// run all of the validator
// controls on the page
Page.Validate();

// capture the result
bool valid = Page.IsValid;

The trouble with this code is that it peppers the page with alarming and unsightly validation messages, which (in this case) we are not ready for the user to see.

So, we should just set the Page.IsValid property back to true, right?

Door v. Window

For a reason that may only ever occur to me after a few too many adult beverages, the Page.IsValid property is read-only. Luckily, when .NET closes a door, it opens a window. The porthole ajar in this instance is that the IsValid property on the BaseValidator class can be set. Since all Validator controls inherit from BaseValidator, we can simply loop through the page’s Validators collection, cast each one down to BaseValidator, and reset its IsValid property, like so:

/// <summary>
/// Resets the Validators on the page.
/// </summary>
protected void ResetValidators()
{
    // query for the page's validators
    List<BaseValidator> validatorList =
        (from BaseValidator v in Page.Validators
         select v).ToList();

    // reset each one
    validatorList.ForEach(
        v => v.IsValid = true);
}

Then we can run the validators, capture the result, and call the reset method to clean up our mess:

/// <summary>
/// Determines if the Validators
/// on the page are valid without
/// displaying unbecoming error
/// messages.
/// </summary>
protected bool PageIsValid()
{
    // validate the page
    Page.Validate();

    // capture the result
    bool valid = Page.IsValid;

    // reset the validators
    ResetValidators();

    return valid;
}

Now, in our page logic, we just have to call this function to determine if the page passes muster:

protected void Page_Load(object sender, EventArgs e)
{
    // don't allow delivery if the address isn't valid
    this.DeliveryCheckbox.Enabled = PageIsValid();
    if (!this.DeliveryCheckbox.Enabled)
    {
        this.DeliveryCheckbox.Checked = false;
    }
}

This time, no unseemly premature error messages!  But wait–

There’s More

The snarky/observant among you are probably wondering about the totally gratuitous LINQ and Lambda Expression work involved in resetting those validators.  In its original form, this code targeted a specific group of validators, not the whole scorch. Yes, I just coined “scorch” as the official collective noun for a page full of validators–like a murder of crows.  But I digress.

In order to narrow things down to address only the ValidationGroup I was aiming for, I had a where clause in my LINQ query:

/// <summary>
/// Resets the Validators on the page.
/// </summary>
protected void ResetValidators(string groupName)
{
    // query for the page's validators
    List<BaseValidator> validatorList =
        (from BaseValidator v in Page.Validators
         where v.ValidationGroup == groupName
         select v).ToList();

    // reset each one
    validatorList.ForEach(
        v => v.IsValid = true);
}

…took advantage of an overload of Page.Validate() that takes a ValidationGroup name:

/// <summary>
/// Determines if the Validators
/// in the given group are valid without
/// displaying unbecoming error messages.
/// </summary>
protected bool PageIsValid(string groupName)
{
    // validate the group
    Page.Validate(groupName);

    // capture the result
    bool valid = Page.IsValid;

    // reset the validators
    ResetValidators(groupName);

    return valid;
}

…and I was validating groups like a ninja on the night of a new moon.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s