VAB: Message Template Tokens

Topics: Validation Application Block
Jun 7, 2007 at 7:08 PM
Hey all,

I know that the VAB supports the usage of Message Template Tokens for the StringLengthValidator (as per link: http://www.pnpguidance.net/Post/ValidationApplicationBlockMessageTemplateTokensResourceFiles.aspx) but is there a way to get the Message Template Tokens working for other validators (e.g. NotNullValidation, or RangeValidator)?

Just thought it would be a lot easier to have generic validation rules in the resource files for all validators, not just the StringLengthValidator.

Thanks,
TJ
Jun 7, 2007 at 10:06 PM
Edited Jun 7, 2007 at 11:09 PM
From the samples that David Hayden posted on http://www.pnpguidance.net/Downloads.aspx there is a sample using the NotNullValidator (along with the StringLengthValidator), I was just curious if the tokens can be used with the other Validators and all that has to happen is to figure out what the {1}, {2} etc. tokens mean on a validator by validator basis.

FYI, here is what I have found out so far. If you can help fill tokens for some of the other validators please go ahead.

NotNullValidator
{0} - Property Value
{1} - Property Name
{2} - Tag in validator

StringLengthValidator
{0} - Property Value
{1} - Property Name
{2} - Tag in validator
{3} - The lower bound
{4} - The lower bound type (In/Exclusive, Ignore)
{5} - The upper bound
{6} - The upper bound type (In/Exclusive, Ignore)

RangeValidator
{0} - Property Value
{1} - Property Name
{2} - Tag in validator
{3} - The lower bound
{4} - The lower bound type (In/Exclusive, Ignore)
{5} - The upper bound
{6} - The upper bound type (In/Exclusive, Ignore)

PropertyComparisonValidator
{0} - Property Value
{1} - Property Name
{2} - Tag in validator
{3} - Compare To Value
{4} - Compare To PropertyName
{5} - ComparisonOperator (e.g. Equal, GreaterThan)
{6} - The upper bound type (In/Exclusive, Ignore)

Thx,
TJ
Jun 8, 2007 at 2:11 AM
I am surprised the tokens are not documented. This would probably be a great WIKI page for someone to add here on CodePlex.

If you have Reflector, you can look through all the validators quickly and find a method:

protected override string GetMessage(object objectToValidate, string key)

Inside the method is a string.Format that displays the tokens so-to-speak. Like this one for the StringLengthValidator:

protected override string GetMessage(object objectToValidate, string key)
{
    return string.Format(CultureInfo.CurrentUICulture, base.MessageTemplate, new object[] { objectToValidate, key, base.Tag, this.rangeChecker.LowerBound, this.rangeChecker.LowerBoundType, this.rangeChecker.UpperBound, this.rangeChecker.UpperBoundType });
}

After the new object[] are the tokens which you mention above for StringLengthValidator.

You can typically find them for all validators this way.

Again, too bad they were not documented.

Regards,

Dave

______________________________

David Hayden
Microsoft MVP C#
Jun 8, 2007 at 11:29 PM
Thanks for the post.

What I was looking at is parsing the PascalCase property name into a two word message. Meaning, instead of displaying "StartDate cannot be empty", I was hoping to tweak the generation of the message to display "Start Date cannot be empty". I managed to modify the message of the StringLength validator by modifying the method you mentioned above; so thanks for that.

Now I am looking for the location where the message for the PropertyComparisonValidator derives it's message. I don't see the GetMessage() method overwritten in the class, and when I add it, my method doesn't seem to be called. It'll just take a little more investigation.

Thanks,
TJ
Jun 11, 2007 at 8:10 PM
I am also looking into how this can be done. What I would LOVE to see is a DisplayName attribute (i.e. DisplayName("Start Date")) that could be applied to a property. The validation engine could use reflection to query this attribute, and if it's not present, use the actual name of the property as a default.

Also, FYI - all the validator tokens are documented. NotNullValidator doesn't list anything specifically because it doesn't use any tokens beyond the defaults ({0}, {1}, and {2}). I've looked through the others, and they appear to be documented.
Jun 15, 2007 at 9:24 PM
Hey there,

I have since found the documentation on the validators, thanks for pointing that out. By changing our project references from the DLL to the actual Validation source code we were able to debug through the EntLib project to find out exactly when/where/how the tokens are used.

We have however implemented a solution to the problem of having the multiple-worded property names defined with Pascal notation. We have created a custom class that contains a method to parse the Pascal notation word into individual words seperated by spaces. In about 15 places inside the Validation project we have added a call to this new method when the message is being generated with the tokens.

For example in the StringLengthValidator.cs file, locate the GetMessage() method. We have changed the return statement to:

return string.Format(CultureInfo.CurrentUICulture,
this.MessageTemplate,
objectToValidate,
custom.CustomMethods.ParsePascalNotation(key),
this.Tag,
this.rangeChecker.LowerBound,
custom.CustomMethods.ConvertRangeBoundaryTypeToText(this.rangeChecker.LowerBoundType),
this.rangeChecker.UpperBound,
custom.CustomMethods.ConvertRangeBoundaryTypeToText(this.rangeChecker.UpperBoundType));

The "key" value is the property name, so by parsing it out at this point will replace the {1} token with the split out, readable value.

In the other overriden GetMessage() methods of the other validators we are calling the ParsePascalNotation method as well.

Anyways...so far so good in terms of how the messages are being displayed. Now that we found a solution, my luck will be that your dream of a DisplayName attribute will probably be added tomorrow or something.

TJ
Jun 18, 2007 at 4:38 PM
Update...Instead of adding a line in 15 different places inside the Validation project, we have moved the call to parse the property names to the two "LogValidationResult" methods inside the Validator.cs class. All of the properties on the target object are sent through the "ParsePascalNotation" method.

Sample:

/ locate the type of the object coming into the method
Type myType = target.GetType();

// for each property defined on the Entity object being validated
foreach (System.Reflection.PropertyInfo myPropertyInfo in myType.GetProperties())
// replace property names in the message with the parsed Pascal notation
newMessage = newMessage.Replace(myPropertyInfo.Name, ParsePascalNotation(myPropertyInfo.Name));

---

happy validating,
TJ