Adding runtime error messages to page validation
One of the requirements when writing a website I once created was the ability to model object constraints in OCL and then validating the current page against those constraints.
The problem with normal validators is that they are designed to validate individual controls rather than a list of constraints on an object. The approach I took was to create a validator which I can place on any web form and add as many errors to as I required.
The first step was to create a WebControl which supported IValidator
When ASP .net validates a page it enumerates all IValidators within its own Validators property, and called IValidator.Validate(). To determine if the page is valid or not it then checks IValidator.IsValid.
To add custom error messages at runtime I decided to create a static validator class which always returns "false" from IsValidator.IsValid. For each error message in my MultiValidator I could then simply create an instance of one of these validators.
Within a webform, I would now
MultiValidator.cs
The problem with normal validators is that they are designed to validate individual controls rather than a list of constraints on an object. The approach I took was to create a validator which I can place on any web form and add as many errors to as I required.
The first step was to create a WebControl which supported IValidator
I then added a list of strings to hold the error strings, and a method to add an error.
public class MultiValidator : WebControl, IValidator
{
}
private ListErrors = new List ();
public void AddError(string message)
{
Errors.Add(message);
}//AddError
When ASP .net validates a page it enumerates all IValidators within its own Validators property, and called IValidator.Validate(). To determine if the page is valid or not it then checks IValidator.IsValid.
To add custom error messages at runtime I decided to create a static validator class which always returns "false" from IsValidator.IsValid. For each error message in my MultiValidator I could then simply create an instance of one of these validators.
[ToolboxItem(false)]Now that the StaticValidator was written, all I needed to do was to add the required IValidator implementations to my MultiValidator class.
internal class StaticValidator : IValidator
{
private string errorMessage;
#region IValidator
void IValidator.Validate()
{
}//Validate
bool IValidator.IsValid
{
get { return false; }
set { }
}//IsValid
#endregion
public string ErrorMessage
{
get { return errorMessage; }
set { errorMessage = value; }
}//ErrorMessage
}
#region IValidator
void IValidator.Validate()
{
isValid = (Errors.Count == 0);
foreach(string error in Errors)
{
StaticValidator validator = new StaticValidator();
validator.ErrorMessage = error;
Page.Validators.Add(validator);
Validators.Add(validator);
}//foreach errors
}//Validate
bool IValidator.IsValid
{
get { return isValid; }
set { isValid = value; }
}//IsValid
#endregion
Within a webform, I would now
- Set "CausesValidation" to false on my submit button
- Validate my object
- Call MultiValidator1.AddError() for each error encountered
- Call Page.Validate()
- Check Page.IsValid as normal
MultiValidator.cs
using System;StaticValidator.cs
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DroopyEyes.Web.Controls
{
public class MultiValidator : WebControl, IValidator
{
#region Members
private bool isValid = true;
private string errorMessage = "";
private ListErrors = new List ();
private ListValidators = new List ();
#endregion
#region IValidator
void IValidator.Validate()
{
isValid = (Errors.Count == 0);
foreach(string error in Errors)
{
StaticValidator validator = new StaticValidator();
validator.ErrorMessage = error;
Page.Validators.Add(validator);
Validators.Add(validator);
}//foreach errors
}//Validate
bool IValidator.IsValid
{
get { return isValid; }
set { isValid = value; }
}//IsValid
#endregion
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.Validators.Add(this);
}
protected override void OnUnload(EventArgs e)
{
if (Page != null)
{
Page.Validators.Remove(this);
foreach(IValidator validator in Validators)
Page.Validators.Remove(validator);
}//Page != null
base.OnUnload(e);
}
public void AddError(string message)
{
Errors.Add(message);
}//AddError
#region Properties
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
public string ErrorMessage
{
get { return errorMessage; }
set { errorMessage = value; }
}//ErrorMessage
#endregion
}
}
using System;
using System.ComponentModel;
using System.Web.UI;
namespace DroopyEyes.Web.Controls
{
[ToolboxItem(false)]
internal class StaticValidator : IValidator
{
private string errorMessage;
#region IValidator
void IValidator.Validate()
{
}//Validate
bool IValidator.IsValid
{
get { return false; }
set { }
}//IsValid
#endregion
public string ErrorMessage
{
get { return errorMessage; }
set { errorMessage = value; }
}//ErrorMessage
}
}
Comments
Now with ASP2.0 a ValidationSummary can have a ValidationGroup. Your great MultiValidator doesn't support this property an so the errors are not showed when this property is set.
Can you help me out to get to work please.
Thanks