I have a form representing a survey that is dynamically generated based on some database configuration. I have a custom server control for rendering the survey (SurveyRenderer) which contains custom server controls for rendering questions (QuestionRenderers). I dynamically add RequiredFieldValidators for questions if they are flagged as being required. I add these validators to the SurveyRenderer‘s control collection.
The gist of the code…
// In SurveyRenderer.CreateChildControls()...
foreach (QuestionRenderer questionRenderer in questionRenderers)
{
if (questionRenderer.Question.IsRequired)
{
Controls.Add(CreateRequiredValidator(questionRenderer));
}
}
The client-side validation works fine — if someone has omitted a required question, the validators catch it and the form doesn’t validate. However if I turn off JavaScript and submit an invalid form, the validators do not seem to work.
On the server-side I am calling Page.Validate() and checking Page.IsValid in the submit button click event handler. Despite submitting a form where required questions have been left blank – something that would be caught client-side – on the server-side Page.IsValid remains True.
// In SurveyPage.aspx...
public void btnSubmit_Click(object sender, EventArgs e)
{
Page.Validate();
if (Page.IsValid)
{
// Always get here, even though the form is not valid and would
// have been caught client-side...
}
}
Should I be adding the validators to the Page’s Control collection, rather than the SurveyRenderer? How come it works on the client-side but not server-side?
UPDATE: My QuestionRenderer is annotated with:
[ValidationProperty("IsValid")]
And the IsValid get method is like so:
// QuestionRenderer.IsValid
public bool IsValid
{
get
{
EnsureChildControls();
if (Question.IsRequired && QuestionIsNotAnswered())
{
return false;
}
return true;
}
}
If I set a breakpoint and step through, I can see that QuestionRenderer.IsValid is being fired OK. It is returning false when it should do. If I go fine-grained and call in btn_submitClick:
// In SurveyPage.aspx...
public void btnSubmit_Click(object sender, EventArgs e)
{
foreach (IValidator validator in Page.Validators)
{
validator.Validate(); // this calls through to QuestionRenderer.IsValid, which returns false...
bool valIsValid = validator.IsValid; // yet this is set to True
}
}
So validator.IsValid is true, even though the call to QuestionRenderer.IsValid returns false. So maybe I haven’t wired something up correctly? Is using [ValidationProperty("IsValid")] not enough?
actually, validation uses
Page.Validatorswhere all the validators are stored (the actual routine is quity tricky) – so it does not matter, where you add them.source of
BaseValidatori would leave them in th view, as you could use
object sender-parameter (which represents the validator) to get the associated control …i believe, your
CreateChildControls– which does the attaching of the validators – is called to late, so it misses the validation phase …could you maybe try to call
EnsureChildControlsinOnLoad-event, to see if it changes something?another chance might be, that your validators are not visible or disabled…
EDIT
according to your edits, i would encourage you to use a
CustomValidator– aRequiredFieldValidatorwill returntrueon each case (property istrueorfalse), because it is not empty 🙂