Generic Error
Generic Error

Reputation: 4477

ASP.Net CustomValidator in a CompositeControl

I present to you a little mystery... the following control is intended to fail validation every time, no matter what, but it does not:

public class Test : CompositeControl
{
    protected override void CreateChildControls()
    {
        Controls.Clear();
        CreateControlHierachy();
        ClearChildViewState();
    }

    void CreateControlHierachy()
    {
        var validator = new CustomValidator
        {
            ErrorMessage = "Can't do that!"
        };

        validator.ServerValidate += (sender, e) =>
        {
            e.IsValid = false;
        };

        Controls.Add(validator);
    }
}

To "fix" the issue, add the following line to CreateControlHierachyand all works as expected:

Controls.Add(new TextBox());

The control is registered in the web.config and placed on a simple page like this:

<uc:Test runat="server" />

Using the debugger on a post back event reveals the following:

What effect is the TextBox having on the validator and what is the correct way to fix this?

Upvotes: 2

Views: 946

Answers (1)

drs9222
drs9222

Reputation: 4508

I found a possible explanation for this. The presence of the TextBox adds a child control to your control that is an IPostbackDataHandler. In order to load the post data the page must first find the control which of course it does by calling FindControl. As FindControl does its thing it eventually accesses the Controls collection of your control. Because your control is a CompositeControl this calls EnsureChildControls which call CreateChildControls.

All of this happens before Validation. Take out the TextBox and the Controls collection is no longer accessed before validation and therefore the validator is not created until after validation (most likely during prerender)

Since your validator doesn't exist at the validation stage it doesn't get called. I recommend adding a call to EnsureChildControls before validation occurs.

    protected override void OnLoad(EventArgs e)
    {
        EnsureChildControls();
        base.OnLoad(e);
    }

Upvotes: 1

Related Questions