Search code examples
fluentvalidation

Fluent validation - group two validators in one custom validator


I have the following validator class:

public class FranchiseInfoValidator : AbstractValidator<FranchiseInfo>
    {
        public FranchiseInfoValidator()
        {
            RuleFor(franchiseInfo => franchiseInfo.FolderName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
            RuleFor(franchiseInfo => franchiseInfo.ExeIconName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
            RuleFor(franchiseInfo => franchiseInfo.FullName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");
            RuleFor(franchiseInfo => franchiseInfo.ShortName).NotEmpty().Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters");        
    }

NotEmpty() and Matches("^[a-zA-Z0-9_.:-]+$").WithMessage("Invalid characters") validators with the custom message are the same for all properties. Is it possible to group them in one custom validator and then write something like this:

RuleFor(franchiseInfo => franchiseInfo.FolderName).SetValidator(new CustomValidator());

I have done some custom validators but not in this scenario. Is this possible? I have found no such example in the documentation. Furthermore, I wonder if this is possible to be done generic so if I have another validator class with properties to apply the same custom validator? Thanks.


Solution

  • yes, it should work with something like that

    public class MyCustomValidator : PropertyValidator
        {
    
            public MyCustomValidator()
                : base("Property {PropertyName} has invalid characters.")
            {
            }
    
            protected override bool IsValid(PropertyValidatorContext context)
            {
                var element = context.PropertyValue  as string;
                return !string.IsNullOrEmpty(element) && Regex.IsMatch(element, "^[a-zA-Z0-9_.:-]+$");
            }
        }
    

    usage : with your code, or create your own extension

    public static class MyValidatorExtensions {
       public static IRuleBuilderOptions<T, string> CheckIfNullAndMatches<T>(this IRuleBuilder<T, string> ruleBuilder) {
          return ruleBuilder.SetValidator(new MyCustomValidator<TElement>());
       }
    }
    

    then usage would be

    RuleFor(franchiseInfo => franchiseInfo.FolderName).CheckIfNullAndMatches();
    

    You could also have a regex as a parameter, if you need a more generic validator...

    doc here