Search code examples
c#fluentvalidation

FluentValidation IRuleBuilderOptions extension method - only run regex validator if value exists


I have the following FluentValidation extension method for validating phone numbers:

public static IRuleBuilderOptions<T, string> MatchPhoneNumber<T>(this IRuleBuilder<T, string> rule)
    => rule.Matches(@"^(1-)?\d{3}-\d{3}-\d{4}$").WithMessage("Invalid phone number");

Which I call:

RuleFor(contact => contact.PhoneNumber).MatchPhoneNumber()

However, I only want the extension method to validate the phone number when the phone number string is not null/empty. I can do this by doing the following:

RuleFor(contact => contact.PhoneNumber)
    .MatchPhoneNumber()
    .When(contact => !string.IsNullOrEmpty(contact.PhoneNumber));

but is there a way I can do this in the extension method itself?


Solution

  • You can change your Regex to accept also empty strings like this: ^$|^(1-)?\d{3}-\d{3}-\d{4}$

    However, I have tried the latest version of FluentValidation (10.3.3) and it does NOT give any error if you pass a null or empty string to the Matches rule. In my example code here, I don't get any error in the result, despite PhoneNumber being Null:

    class Program
    {
        static void Main(string[] args)
        {
            var contact = new Contact();
            var contactValidator = new ContactValidator();
            var result = contactValidator.Validate(contact);
            Console.WriteLine(result.IsValid); // This returns true with null phone number
        }
    }
    
    public class Contact
    {
        public string PhoneNumber { get; set; }
    }
    
    public class ContactValidator : AbstractValidator<Contact>
    {
        public ContactValidator()
        {
            RuleFor(contact => contact.PhoneNumber)
                .MatchPhoneNumber();
        }
    }
    
    public static class Extensions
    {
        public static IRuleBuilderOptions<T, string> MatchPhoneNumber<T>(this IRuleBuilder<T, string> rule)
            => rule.Matches(@"^(1-)?\d{3}-\d{3}-\d{4}$").WithMessage("Invalid phone number");
    }
    
    

    Are you using a different way to define your validator?