Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FluentValidation - validating across multiple properties

Have a form where a user can enter start date/time and end date/time for an event. Here's the validator so far:

public class EventModelValidator : AbstractValidator<EventViewModel>     {         public EventModelValidator()         {             RuleFor(x => x.StartDate)                 .NotEmpty().WithMessage("Date is required!")                 .Must(BeAValidDate).WithMessage("Invalid date");             RuleFor(x => x.StartTime)                 .NotEmpty().WithMessage("Start time is required!")                 .Must(BeAValidTime).WithMessage("Invalid Start time");             RuleFor(x => x.EndTime)                 .NotEmpty().WithMessage("End time is required!")                 .Must(BeAValidTime).WithMessage("Invalid End time");             RuleFor(x => x.Title).NotEmpty().WithMessage("A title is required!");         }           private bool BeAValidDate(string value)         {             DateTime date;             return DateTime.TryParse(value, out date);         }          private bool BeAValidTime(string value)         {             DateTimeOffset offset;             return DateTimeOffset.TryParse(value, out offset);         }      } 

Now I'd also like to add validation that EndDateTime > StartDateTime (combined Date+Time properties), but not sure how to go about it.

Edit: To clarify, I need to somehow combine EndDate + EndTime/StartDate + StartTime i.e. DateTime.Parse(src.StartDate + " " + src.StartTime) and then validate EndDateTime vs. StartDateTime - how do I do that?

like image 623
seekay Avatar asked Oct 09 '11 05:10

seekay


1 Answers

Finally got it working after I re-read the documentation: "Note that there is an additional overload for Must that also accepts an instance of the parent object being validated."

public class EventModelValidator : AbstractValidator<EventViewModel>     {         public EventModelValidator()         {             RuleFor(x => x.StartDate)                 .NotEmpty().WithMessage("Date is required!")                 .Must(BeAValidDate).WithMessage("Invalid date");             RuleFor(x => x.StartTime)                 .NotEmpty().WithMessage("Start time is required!")                 .Must(BeAValidTime).WithMessage("Invalid Start time");             RuleFor(x => x.EndTime)                 .NotEmpty().WithMessage("End time is required!")                 .Must(BeAValidTime).WithMessage("Invalid End time")                 // new                 .Must(BeGreaterThan).WithMessage("End time needs to be greater than start time");             RuleFor(x => x.Title).NotEmpty().WithMessage("A title is required!");         }           private bool BeAValidDate(string value)         {             DateTime date;             return DateTime.TryParse(value, out date);         }          private bool BeAValidTime(string value)         {             DateTimeOffset offset;             return DateTimeOffset.TryParse(value, out offset);         }         // new         private bool BeGreaterThan(EventViewModel instance, string endTime)         {             DateTime start = DateTime.Parse(instance.StartDate + " " + instance.StartTime);             DateTime end = DateTime.Parse(instance.EndDate + " " + instance.EndTime);             return (DateTime.Compare(start, end) <= 0);         }     } 

There might be a cleaner/more legant way to do this, but for now, it worksforme.

like image 96
seekay Avatar answered Sep 20 '22 16:09

seekay