FluentValidation — проверка нескольких свойств

Создайте форму, в которой пользователь может ввести дату/время начала и дату/время окончания события. Вот валидатор:

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);
        }

    }

Теперь я также хотел бы добавить проверку того, что EndDateTime > StartDateTime (объединенные свойства даты и времени), но не знаю, как это сделать.

Редактировать: Чтобы уточнить, мне нужно каким-то образом объединить EndDate + EndTime/StartDate + StartTime, т.е. DateTime.Parse(src.StartDate + " " + src.StartTime), а затем проверить EndDateTime и StartDateTime - как это сделать Я делаю это?


person seekay    schedule 09.10.2011    source источник


Ответы (2)


Наконец-то это заработало после того, как я перечитал документацию: "Обратите внимание, что является дополнительной перегрузкой для Must, которая также принимает экземпляр проверяемого родительского объекта."

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);
        }
    }

Возможно, есть более чистый/легальный способ сделать это, но пока он работает.

person seekay    schedule 10.10.2011
comment
Можно ли сделать то же самое на стороне клиента? - person SMC; 09.08.2013
comment
Это больше не действует в FluentValition. Это правильный ответ: stackoverflow.com/a/20546097/59119 - person Natrium; 31.08.2016

Вы можете попробовать использовать правило GreaterThan:

RuleFor(x => x.EndDate)
    .GreaterThan(x => x.StartDate)
    .WithMessage("end date must be after start date");
person Darin Dimitrov    schedule 09.10.2011
comment
Извините, просто добавил уточнение выше. Необходимо объединить дату и время и затем подтвердить - person seekay; 10.10.2011
comment
Можно ли сделать то же самое на стороне клиента? или проверьте здесь: stackoverflow.com/questions/18142489/ - person SMC; 09.08.2013