Search code examples
c#validationfluentvalidation

FluentValidation of optional object in list


Is there a way to use FluentValidation using the value of an object property for objects in a list that may not exist in the list? I think this is possible but I can't figure out how to code it. Using the code sample below, if an action record has an action value of "Approve", is is possible to make sure the email field is not empty? For sake of argument, assume we do NOT want this rule to apply for other objects in the list that may have a different value in the Action field.

class Action_Record
{
    public string Type { get; set; }
    public string Action { get; set; }
    public string Comments { get; set; }
    public string Action_By_Email { get; set; }
    public DateTime? Action_Start { get; set; }
    public DateTime? Action_End { get; set; }
    public Action_Record()
    {
        this.Type = "";
        this.Action = "";
        this.Comments = "";
        this.Action_By_Email = "";
        this.Action_Start = null;
        this.Action_End = null;
    }
}

Approver_Recs = new List<Action_Record>();
Action_Record o = new Action_Record();
o.Type = "Finance";
o.Action = "Approve";

Approver_Recs.Add(o);

Solution

  • With the latest version of "FluentValidation", this should work:

    Create a validator class which takes the collection object as input. Then only for Action="Approve" case we invoke the EmailValidator.

    public class ActionRecordValidator : AbstractValidator<List<Action_Record>>
    {
        public ActionRecordValidator()
        {
            RuleForEach(x => x).Where(x => x.Action == "Approve").SetValidator(new EmailValidator());
        }
    }
    
    public class EmailValidator : AbstractValidator<Action_Record>
    {
        public EmailValidator()
        {
           RuleFor(x => x.Action_By_Email).NotNull().NotEmpty().WithMessage("Email is required when Approve action is chosen.");
        }
    }
    

    Calling code sample:

            var Approver_Recs = new List<Action_Record>();
            Action_Record o = new Action_Record() { Type = "Finance" , Action = "Reject" };
            Approver_Recs.Add(o);
            Action_Record o2 = new Action_Record() { Type = "Finance" , Action = "Approve" };
    
            ActionRecordValidator validator = new ActionRecordValidator();
            Approver_Recs.Add(o2);
            ValidationResult results = validator.Validate(Approver_Recs);
            if (!results.IsValid)
            {
                foreach (var failure in results.Errors)
                {
                    Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
                }
            }