Wednesday, December 31, 2008

Validation Application Block Gotchas

The Microsoft Enterprise Library's Validation Application Block is really neat for validation of data, but with the way it's been implemented, it can be difficult for developers to diagnose problems with it, especially when declaratively defining the validators using XML. Often, a validator returns true even for invalid data. Let's look at a few common causes:

1. The RuleSet specified does not exist

When you use a validator defined as
Validator<NitinR> validator = ValidationFactory.CreateValidator<NitinR>("Rule1");
the Validation Application Block looks around for Rule1 and if it doesn't find a definition, it simply indicates that the object being validated is true. I'm pretty sure everyone would expect it to throw an exception, but it doesn't!

2. The Member Is Of An Incorrect Type

If you've defined a validation for a field, but change it to a property while re-factoring, the library simply assumes that you haven't defined any validation for that property so it returns a ValidationResults object with IsValid set to true.

3. NotNullValidator On A Value Type

If you think the NotNullValidator is going to tell you that a value-typed member variable has not been initialized, think again. For an Int32 member, the default value is a zero. When the NotNullValidator looks at the Int32 member, it sees the value zero instead of a null, so the data is valid. To get around this issue, add a "?" suffix (C#) to the data type to declare the variable as a null-able value type.

4. RelativeDateTimeValidator Needs Negative Values For Dates In The Past

This one sounds obvious but was a bit tricky. It took me a while to figure out through trial-and-error (as opposed to reading the source code or reverse engineering) that if I want to refer to a date in the past, I'm supposed to use negative values, especially since the Enterprise Library Configuration tool reports a configuration error. (I'm guessing the error from the configuration tool is because my lowerBound was set to -1 with the lowerUnit Day and the upperBound was set to -5 with the UpperUnit Seconds, and the configuration tool ignores the units so it sees the lowerBound value greater than the upperBound)

No comments: