How to validate Entity properties?

Topics: Validation Application Block
Feb 22, 2007 at 7:41 PM
Edited Feb 22, 2007 at 8:09 PM
I have 3 questions on using validators:

1) Validator attributes on private members

I am trying to implement validation code via the VAB for the first time. I have setup all of my entities' private member variables with Validator attributes (StringLength, NotNull, Int32Range, and Regex).

Following is a sample entity with its member variable's setup with validator attributes:
StringLengthValidator(0,20, Tag="String length problem")
NotNullValidator(Tag="Field cannot be null")
private string _Name;
StringLengthValidator(0,15, Tag="String length problem")
NotNullValidator(Tag="Field cannot be null")
private string _Address;

Here is the code snippet from my business class object which validates the entity prior to an insert:
ValidationResults results = null;
foreach (Entity item in items)
{
results = Validation.Validate(item);
if (!results.IsValid)
throw new InvalidOperationException("Validation error found.");
}

I was expecting this to work, but it did not. I then moved the validaton attributes to the public properties instead and it worked. Does this seem right?

2) How to use ValidationResults to get Key/Message

Also, how do I work with the ValidationResults? I assume it is a collection of ValidationResult object but there is no way to get at the individual objects?

I haven't figured out how to use the FindAll method of the ValidationResults object yet, so that might be the problem.

3) Validate method - which is the recommended way to call the method?

Validator<Entity> validator = ValidationFactory.CreateValidator<Entity>();
results = validator.Validate(item);
results = Validation.Validate<Entity>(item);
results = Validation.Validate(item);
Feb 22, 2007 at 7:55 PM
Edited Feb 22, 2007 at 9:05 PM
Figured out 2 & 3. Still need some clarification around #1. Thanks.
Feb 22, 2007 at 9:08 PM
Hi Greif -

1) This behavior is by design. Private members are not designed to be accessible from outside your class, so allowing the validation block to access these would break enapsulation. In many cases you will create public properties that wrap your private fields, in which case the best approach is to apply the validation attributes to these properties.

2) You can iterate through the ValidationResults collection using a foreach statement, eg:
foreach (ValidationResult result in results)
{
    Console.WriteLine(result.Message);
}
The FindAll method is used to filter the ValidationResults collection by tag. If you aren't using different tags for different validators, there's no reason to use this method.

3) All of these approaches have their uses, that's why we created them :-)
Creating a validator with a factory is particularly useful if you want to reuse the same validator instance multiple times - you can create it once and use it to validate multiple objects without incurring the overhead of creating the validator each time. The generic-based methods give you increased type safety and also let you specify exactly which type you want to read the validators for (which may or may not be the same as the type of the object reference in polymorphic situations). If you aren't dealing with complex inheritance hierarchies and are not validating objects of the same type over and over, the last example you gave is obviously the simplest.

HTH
Tom