Reputation: 20407
I have a webform with two custom validators:
<asp:TextBox ID="txtResourceStartDate" runat="server"
CssClass="textBox mandatory dateField" />
<asp:CustomValidator ID="valResourceStartDateIsDate" runat="server"
ControlToValidate="txtResourceStartDate" Display="None"
ErrorMessage="Start date must be a valid date"
OnServerValidate="Date_ServerValidate" />
<asp:TextBox ID="txtResourceEndDate" runat="server"
CssClass="textBox mandatory dateField" />
<asp:CustomValidator ID="valResourceEndDateIsDate" runat="server"
ControlToValidate="txtResourceEndDate" Display="None"
ErrorMessage="End date must be a valid date"
OnServerValidate="Date_ServerValidate" />
<asp:CustomValidator Display="None" Text="" ID="valForStartEndDate" runat="server"
OnServerValidate="ValidateStartEndDate"
ErrorMessage="Last day must be greater than or equal to first day" />
protected void Date_ServerValidate(object source, ServerValidateEventArgs args)
{
DateTime outDate;
args.IsValid = DateTime.TryParse(args.Value, out outDate);
}
protected void ValidateStartEndDate(object sender, ServerValidateEventArgs e)
{
e.IsValid = DateTime.Parse(txtResourceEndDate.Text) >=
DateTime.Parse(txtResourceStartDate.Text);
}
The problem is that the ValidateStartEndDate
validator is firing before the Date_ServerValidate
validator, so if the date is not valid, a format exception is thrown on DateTime.Parse
. Obviously this validator could check for a valid date before parsing, but I’d really prefer to have a discrete validator with an appropriate message.
So the question is this: what determines the sequence with which the validators fire? Unless I’m missing something, this is not declared at the tag level.
Upvotes: 3
Views: 3436
Reputation: 2574
Validation control execution order is determined by the order of the controls in the ValidatorCollection
returned by Page.Validators
. This order is, in turn, determined by the order of the validation controls in the markup, with some exceptions (e.g. validators within data-bound controls will get added to the collection later, and so will be at the end).
If you set CausesValidation=false
on your button and then trigger validation manually with Page.Validate
, you can use the Add
and Remove
methods on the ValidatorCollection
to change the execution order:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) {
// move myValidator to the very end, so it executes last
Validators.Remove(myValidator);
Validators.Add(myValidator);
}
}
Then, later on in the triggering control:
protected void myButton_Click(object sender, EventArgs e)
{
Page.Validate();
if (!Page.IsValid) { return; }
// validation passed, proceed...
}
Disclaimer: all of this is empirical, I haven't found MSDN docs to back it up, but it seems to work.
Upvotes: 0
Reputation: 460238
You can't count on a certain sequence the validators will fire and also you shouldnt. You have to make sure for yourself that the order is irrelevant.
So you could
Some interesting infos about Page-Validation: http://msdn.microsoft.com/en-us/library/aa479045.aspx
Upvotes: 2