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?
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.