Проверка модели MVC на дату
Есть ли какая-либо проверка по умолчанию для MVC 5, где я могу установить минимальное и максимальное значение даты?
В моей модели мне нужна проверка даты
public class MyClass
{
[Required(ErrorMessage="Start date and time cannot be empty")]
//validate:Must be greater than current date
[DataType(DataType.DateTime)]
public DateTime StartDateTime { get; set; }
[Required(ErrorMessage="End date and time cannot be empty")]
//validate:must be greater than StartDate
[DataType(DataType.DateTime)]
public DateTime EndDateTime { get; set; }
}
Ps: Согласно этому сайту Asp.Net, существует проблема с использованием валидатора Range
для DateTime, и это не рекомендуется.
Примечание. Проверка jQuery не работает с атрибутом Range и DateTime. Например, следующий код всегда отображает ошибка проверки на стороне клиента, даже если дата указана в указанный диапазон:
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
Вам необходимо отключить проверку даты jQuery, чтобы использовать атрибут Range с DateTime. Как правило, не очень хорошая практика скомпилировать даты в ваших моделях, поэтому использование атрибута Range и DateTime не рекомендуется.
Я также знаю, что есть пакеты Nuget, такие как Свободная проверка и Foolproof, что делает трюк для проверки и проверки, если одна дата больше, чем другая, но я хотел знать, есть ли по умолчанию что-то, чтобы проверить дату min и max.
Из того, что я увидел в Что нового в MVC 5.1, есть поддержка MaxLength
и MinLength
.
Ответы
Ответ 1
Я бы сделал это с интерфейсом IValidatableObject
из System.ComponentModel.DataAnnotations, который позволяет добавлять дополнительные правила проверки, где вы можете сделать гораздо большую проверку. Добавьте интерфейс в свой класс, а затем внедрите метод Validate
, где вы можете сравнить StartDateTime с текущей датой/временем, а также сравнить EndDateTime с StartDateTime, например.
public class MyClass : IValidatableObject
{
[Required(ErrorMessage="Start date and time cannot be empty")]
//validate:Must be greater than current date
[DataType(DataType.DateTime)]
public DateTime StartDateTime { get; set; }
[Required(ErrorMessage="End date and time cannot be empty")]
//validate:must be greater than StartDate
[DataType(DataType.DateTime)]
public DateTime EndDateTime { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> results = new List<ValidationResult>();
if (StartDateTime < DateTime.Now)
{
results.Add(new ValidationResult("Start date and time must be greater than current time", new []{"StartDateTime"}));
}
if (EndDateTime <= StartDateTime)
{
results.Add(new ValidationResult("EndDateTime must be greater that StartDateTime", new [] {"EndDateTime"}));
}
return results;
}
}
Единственным потенциальным недостатком этого является то, что Validate
работает на стороне сервера, а не в проверке jQuery.
Ответ 2
Нет необходимости отключать проверку даты jQuery (и это может вызвать другие проблемы). Вам просто нужно переопределить метод range
$.validator
.
По умолчанию он работает с числовыми значениями (а затем возвращается к сопоставлению строк), поэтому вы можете добавить следующие script (после jquery.validate.js
и jquery.validate.unobtrusive.js
, но не завернутые в $(document).ready
$.validator.methods.range = function(value, element, param) {
if ($(element).attr('data-val-date')) {
var min = $(element).attr('data-val-range-min');
var max = $(element).attr('data-val-range-max');
var date = new Date(value).getTime();
var minDate = new Date(min).getTime();
var maxDate = new Date(max).getTime();
return this.optional(element) || (date >= minDate && date <= maxDate);
}
// use the default method
return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
};
Затем вы можете использовать RangeAttribute
в своем свойстве
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
public DateTime Date { get; set; }
Ответ 3
Обычно я использую это решение, когда хочу проверить что-то на сервере.
Я знаю, что вы можете положиться на модель проверки, которую использует MVC, но когда я делаю проверки, я пытаюсь использовать отдельный проект, если мне нужно сделать unit test для них. Допустим, у вас есть два приложения: один рабочий стол и один веб-сайт, тогда оба могут совместно использовать ValidationProject вместо повторения кода в обоих приложениях для одного и того же "Просмотр" / "Экран". Идея здесь заключается в том, чтобы изолировать проект валидации как независимый проект вашего решения.
Итак, вы можете скачать проект FluentValidation из NuGet, FluentValidation использует правила внутри конструктора, вы можете увидеть документацию здесь https://github.com/JeremySkinner/FluentValidation/wiki p >
Например, можно использовать правило "Дата", например, вы можете поместить правила для своего значения min и вашего максимального значения:
public class CustomerValidator: AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(customer => customer.startDate)
.NotNull()
.WithMessage("You should select a start date")
.Must(d => d.HasValue && d.Value <= DateTime.Today)
.WithMessage("The start date should not be greather than current month/year");
}
Теперь внутри вашего контроллера
[HttpPost]
public ActionResult Index(Customer c)
{
if(ModelState.IsValid)
{
var validator= new CustomerValidator();
var valResult = validator.Validate(c);
if (valResult.Errors.Count != 0)
{
valResult.Errors.ForEach(x => ModelState.AddModelError(x.PropertyName, x.ErrorMessage));
return View(vm);
}
//Your code here
}
}
Ответ 4
Я думаю, что просто добавление атрибута "Range" будет работать
[Range(typeof(DateTime), "01/01/1900", "06/06/2079", ErrorMessageResourceType = typeof(Resources.Patient), ErrorMessageResourceName = "DateOfBirth_Range")]