views:

308

answers:

1

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:

  • The validator is in the control hierachy on the page, as expected.
  • The validator is not registered in Page.Validators.
  • Both Page.IsValid and validator.IsValid are still true.

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

+1  A: 

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);
    }
drs9222
Right you are. Unless something triggers it, EnsureChildControls doesn't get called until PreRender which is well after validation has occured. Thanks!
Generic Error