Introduction
One month ago, I was working on an ASP.NET project that am I still working on and I came a cross a point where I wanted to have a centralized Validation Summary and Multi-Validation Groups. Of course, with no hesitation I added a centralized validation summary and started to do my validation ... but unfortunately, I wasn't lucky enough for that to work !!!
The Problem !!!
At the beginning, I thought I was doing something wrong, my scenario was more than basic and very EXPECTED to occur, two set of controls, each one with a validation group, and one validation summary. I do my validation on the server side using Page.Validate(ValidationGroupName)
for each one as follows:
Page.Validate("ValidationGroup1");
Page.Validate("ValidationGroup2");
if (Page.IsValid)
{
}
else
{
}
The funny thing is that if I wanted to show Validation Messages from both ValidationGroup1
and ValidationGroup2
, I have to have TWO validation summaries, the first one is set to use the ValidationGroup1
and the other one is set to use the ValidationGroup2. In other words for each validation group you have or is going to occur in that page, you have to have n validation summaries.
Now that made me angry enough to have my own validation summary.
The Investigation
To solve this problem, I started with the Internet, searching for an article, a post or a blog that has the solution to such a basic scenario which is occurring for years now! Unbelievably I couldn't find a descent solution ! and I mean it ! The best thing I found is something that involved creating duplicate validators at runtime and adding them to the host page. I know it sounds crazy, but seriously that was the best solution !!
So I started to investigate the ASP.NET Validation Summary control itself, I took a sneak peak into its source code to figure out why it's not supporting more than one validation group and I found the below:
internal string[] GetErrorMessages(out bool inError)
{
string[] strArray = null;
inError = false;
int num = 0;
ValidatorCollection validators = this.Page.GetValidators(this.ValidationGroup);
for (int i = 0; i < validators.Count; i++)
{
IValidator validator = validators[i];
if (!validator.IsValid)
{
inError = true;
if (validator.ErrorMessage.Length != 0)
{
num++;
}
}
}
if (num != 0)
{
strArray = new string[num];
int index = 0;
for (int j = 0; j < validators.Count; j++)
{
IValidator validator2 = validators[j];
if ((!validator2.IsValid && (validator2.ErrorMessage != null)) &&
(validator2.ErrorMessage.Length != 0))
{
strArray[index] = string.Copy(validator2.ErrorMessage);
index++;
}
}
}
return strArray;
}
Note the Italic bolded line of code; the validation summary uses its host page to get the validators with the same validation group as that of the validation summary !! Therefore there is no way it gets more than one validation group to be supported ! Of course, the GetValidators(ValidationGroupName)
method doesn't treat null
or empty
validation group as a special case, it's another case as if you have specified a validation group, so only one validation group will be retrieving its validators.
The Solution
To solve this issue, at first I thought of having a Custom Control that behaves exactly as the Current ASP.NET Validation Summary with extra feature of enabling to support any validation group on the hosting page.
First, I have simply added a new Enumeration ValidationGroupMode
:
public enum ValidationGroupMode
{
SingleValidationGroup = 0,
AllValidationGroups = 1
}
Secondly, I tweaked the GetErrorMessages
method to become as follows:
internal string[] GetErrorMessages(out bool inError)
{
string[] strArray = null;
inError = false;
int num = 0;
ValidatorCollection validators
= this.ValidationGroupMode == ValidationGroupMode.AllValidationGroups ?
this.Page.Validators : this.Page.GetValidators(this.ValidationGroup);
for (int i = 0; i < validators.Count; i++)
{
IValidator validator = validators[i];
if (!validator.IsValid)
{
inError = true;
if (validator.ErrorMessage.Length != 0)
{
num++;
}
}
}
if (num != 0)
{
strArray = new string[num];
int index = 0;
for (int j = 0; j < validators.Count; j++)
{
IValidator validator2 = validators[j];
if ((!validator2.IsValid && (validator2.ErrorMessage != null))
&& (validator2.ErrorMessage.Length != 0))
{
strArray[index] = string.Copy(validator2.ErrorMessage);
index++;
}
}
}
return strArray;
}
Simply in case I wanted to have all validation groups to share the same validation summary, I got all validators on the page using this.Page.Validators
.
Final Words
I hope this article was useful, and I am attaching the code for the Custom Validation Summary. I made sure that it's compatible with Framework 2.0 and above.
History
- V 1.0 Created the article