EntLib Validation Application Block - Required String Validator
In a previous post I discussed validating strings with the VAB in the context of ASP.NET applications. In summary, you must have a NotNullValidator and also a StringLengthValidator that prevents a string length of zero on the lower bound and prevents a string length above your upper bound (e.g., 50 characters). That attribute might look like this:
[StringLengthValidator(1, 50, MessageTemplate="First Name must be 1-50 characters.")]
But the problem is that the StringLengthValidator is really doing 2 jobs - one to check if the user entered a value and another to check the upper bound. Although including the NotNullValidator complete and correct, it doesn't do much in the context of asp.net applications which default to an empty string.
So from a user perspective, it would be nice to have one message if the user leaves it blank and another message if they've exceed the upper bound (or didn't follow an appropriate Regex pattern, etc., etc.). In other words, it would be nice to have a RequiredStringValidator so we could write our business object like this (notice we no longer have to care about the lower bound on the string length validator):
public class Person { [RequiredStringValidator(MessageTemplate = "First Name is required.")] [StringLengthValidator(50, MessageTemplate = "First Name must be less than 50 characters.")] public string FirstName { get; set; } }
Also, specifiying a MessageTemplate on the RequiredStringValidator is optional.
So creating your own custom validator to do this is actually quite easy. The complete implementation follows:
public class RequiredStringValidatorAttribute : ValueValidatorAttribute { protected override Validator DoCreateValidator(Type targetType) { return new RequiredStringValidator(this.MessageTemplate, this.Negated); } } public class RequiredStringValidator : ValueValidator { public RequiredStringValidator(string messageTemplate, bool negated) : base(messageTemplate, null, negated) { } protected override void DoValidate(string objectToValidate, object currentTarget, string key, ValidationResults validationResults) { if (string.IsNullOrEmpty(objectToValidate) != Negated) { LogValidationResult(validationResults, GetMessage(objectToValidate, key), currentTarget, key); } } protected override string DefaultNegatedMessageTemplate { get { return "Field cannot have a value."; } } protected override string DefaultNonNegatedMessageTemplate { get { return "Field is required."; } } }
I've supported Negations for completeness but I can't really think of a real-world example where you'd want to use it in this context.
So overall, the RequiredStringValidator check for both null and empty string. Thus, you don't have to feel like you're kludging the StringLengthValidator into doing two different jobs.