Validation for the Wishy-Washy
In .NET 3.0 we have a newfangled class known as ValidationResult. It's returned from a ValidationRule's Validate method and has a boolean property representing whether the validation succeeded, as well as a string property for the error message if it failed.
In my current project, however, a simple boolean value for validity isn't enough. There are a few edge cases where the validation depends on feedback from the user - an answer to a simple yes/no question.
So I've knocked up a very simple ValidationResult class of my own, which uses a Nullable boolean to represent the IsValid property, where a null value indicates that validation can't be determined until the user is asked the question posted in the Message property.
I've also added some static methods in lieu of public constructors so that the code is a bit more readable. You can return ValidationResult.Success, ValidationResult.Failure(reason) or ValidationResult.Ask(question) from your validation routine.
Keep in mind that this is not a drop-in replacement for the "real" ValidationResult. It's designed to be used in my own (.NET 2.0) project and has no relation to the new class. Here's the code!
public class ValidationResult
{
private static ValidationResult _success = new ValidationResult(true);
public static ValidationResult Success
{
get { return _success; }
}
public static ValidationResult Failure(string message)
{
return new ValidationResult(false, message);
}
public static ValidationResult Failure(string message, params object[] args)
{
return Failure(string.Format(message, args));
}
public static ValidationResult Ask(string message)
{
return new ValidationResult(message);
}
public static ValidationResult Ask(string message, params object[] args)
{
return Ask(string.Format(message, args));
}
private ValidationResult(bool? isValid, string message)
{
_isValid = isValid;
_message = message;
}
private ValidationResult(bool isValid)
: this(isValid, string.Empty)
{
}
private ValidationResult(string prompt)
: this(null, prompt)
{
}
private bool? _isValid;
private string _message;
/// <summary>
/// Whether validation was successful. If null, validation depends on the user's
/// response to the question in <see cref="Message">Message</see>.
/// </summary>
public bool? IsValid
{
get { return _isValid; }
set { _isValid = value; }
}
/// <summary>
/// The error message if validation failed, or the question to ask the user if
/// validity could not be determined.
/// </summary>
public string Message
{
get { return _message; }
set { _message = value; }
}
}
Comments
# paul stovell
19/11/2007 10:38 AM
I like the idea of the business layer returning abstract classes of validation results, e.g:
ValidationResult
ErrorValidationResult
WarningValidationResult
InformationValidationResult (name is too long, will be truncated)
PromptValidationResult
The cool thing is in WPF you can use a ContentPresenter and data templates to display the error differently based on the ValidationResult class.
# mabster
19/11/2007 10:56 AM
Certainly a derived class (PromptValidationResult in your list) would work too. In this case I just needed something very simple.
Having a hierarchy of ValidationResult descendants might complicate things a bit. Surely 99.9% of the time you're just interested in whether it's valid and if not, why not? Can you elaborate (perhaps in a blog post) on how you would use a series of derived validation classes, Paul?