Search code examples
c#asp.net-mvc-3validationfluentvalidation

Validating against a string containing comma delimited emails


I'm trying to validate this property in MVC model, which can contain zero or more email addresses delimited by comma:

public class DashboardVM
{
    public string CurrentAbuseEmails { get; set; }
    ...
}

The question is how do I do this using the built-in fluent validation rule for Email Address? For now I have a solution using Must and regular expression which works, but I don't find it .. elegant enough.

    public DashboardVMValidator()
    {
        RuleFor(x => x.CurrentAbuseEmails).Must(BeValidDelimitedEmailList).WithMessage("One or more email addresses are not valid.");
    }

    private bool BeValidDelimitedEmailList(string delimitedEmails)
    {
        //... match very very long reg. expression
    }

So far the closest solution including RuleFor(...).EmailAddress() was creating a custom Validator below and call Validate on each email from the string, but that didn't work for some reason (AbuseEmailValidator wasn't able to get my predicate x => x - when calling validator.Validate on each email).

public class AbuseEmailValidator : AbstractValidator<string>
{
    public AbuseEmailValidator()
    {
        RuleFor(x => x).EmailAddress().WithMessage("Email address is not valid");
    }
}

Is there way to do this in some simple manner? Something similar to this solution, but with one string instead of list of strings, as I can't use SetCollectionValidator (or can I?): How do you validate against each string in a list using Fluent Validation?


Solution

  • You can try something like this:

    public class InvoiceValidator : AbstractValidator<ContractInvoicingEditModel>
    {
        public InvoiceValidator()
        {
            RuleFor(m => m.EmailAddressTo)
                .Must(CommonValidators.CheckValidEmails).WithMessage("Some of the emails   provided are not valid");
        }
    }
    
    public static class CommonValidators
    {
        public static bool CheckValidEmails(string arg)
        {
            var list = arg.Split(';');
            var isValid = true;
            var emailValidator = new EmailValidator();
    
            foreach (var t in list)
            {
                isValid = emailValidator.Validate(new EmailModel { Email = t.Trim() }).IsValid;
                if (!isValid)
                    break;
            }
    
            return isValid;
        }
    }
    public class EmailValidator : AbstractValidator<EmailModel>
    {
        public EmailValidator()
        {
            RuleFor(x => x.Email).EmailAddress();
        }
    }
    
    public class EmailModel
    {
        public string Email { get; set; }
    }
    

    It seems to work fine if you use an intermediary poco. My emails are separated by ";" in this case. Hope it helps.