Аннотации данных mvc4 сравнивают две даты
У меня есть эти два поля в моей модели:
[Required(ErrorMessage="The start date is required")]
[Display(Name="Start Date")]
[DisplayFormat(DataFormatString = "{0,d}")]
public DateTime startDate { get; set; }
[Required(ErrorMessage="The end date is required")]
[Display(Name="End Date")]
[DisplayFormat(DataFormatString = "{0,d}")]
public DateTime endDate{ get; set; }
Я требую, чтобы endDate
был больше, чем startDate
. Я попытался использовать [Compare("startDate")]
, но это работает только для равных операций.
Что я должен использовать для операции "больше"?
Ответы
Ответ 1
Взгляните на Свободная проверка или Проверка надежности MVC: это может помочь вам.
С Foolproof, например, есть аннотация [GreaterThan("StartDate")]
, которую вы можете использовать в свойстве даты.
Или, если вы не хотите использовать другие библиотеки, вы можете реализовать свою собственную проверку, реализовав IValidatableObject
в своей модели:
public class ViewModel: IValidatableObject
{
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (EndDate < StartDate)
{
yield return
new ValidationResult(errorMessage: "EndDate must be greater than StartDate",
memberNames: new[] { "EndDate" });
}
}
}
Ответ 2
Интерфейс IValidatableObject обеспечивает способ проверки объекта, который реализует метод IValidatableObject.Validate(ValidationContext validationContext). Этот метод всегда возвращает объект IEnumerable. Для этого вам необходимо создать список объектов и ошибок ValidationResult и вернуть их. Пустой список означает подтверждение ваших условий. Это выглядит следующим образом в mvc 4...
public class LibProject : IValidatableObject
{
[Required(ErrorMessage="Project name required")]
public string Project_name { get; set; }
[Required(ErrorMessage = "Job no required")]
public string Job_no { get; set; }
public string Client { get; set; }
[DataType(DataType.Date,ErrorMessage="Invalid Date")]
public DateTime ExpireDate { get; set; }
IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
{
List < ValidationResult > res =new List<ValidationResult>();
if (ExpireDate < DateTime.Today)
{
ValidationResult mss=new ValidationResult("Expire date must be greater than or equal to Today");
res.Add(mss);
}
return res;
}
}
Ответ 3
В значительной степени заимствуя ответы Александра Гора и Хайме Марина на связанный вопрос StackOverflow 1, я создал пять классов, которые позволяют сравнивать два поля в одной модели с использованием операторов GT, GE, EQ, LE и LT при условии, что они реализуют IComparable. Так, например, его можно использовать для пар дат, времени, целых чисел и строк.
Было бы неплохо объединить их все в один класс и использовать оператор в качестве аргумента, но я не знаю как. Я оставил три исключения как есть, потому что, если их выбросить, они действительно представляют проблему проектирования формы, а не проблему пользовательского ввода.
Вы просто используете его в своей модели следующим образом, и файл с пятью классами выглядит следующим образом:
[Required(ErrorMessage = "Start date is required.")]
public DateTime CalendarStartDate { get; set; }
[Required(ErrorMessage = "End date is required.")]
[AttributeGreaterThanOrEqual("CalendarStartDate",
ErrorMessage = "The Calendar end date must be on or after the Calendar start date.")]
public DateTime CalendarEndDate { get; set; }
using System;
using System.ComponentModel.DataAnnotations;
//Contains GT, GE, EQ, LE, and LT validations for types that implement IComparable interface.
///info/1263463/custom-validation-attributes-comparing-two-properties-in-the-same-model
namespace DateComparisons.Validations
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AttributeGreaterThan : ValidationAttribute
{
private readonly string _comparisonProperty;
public AttributeGreaterThan(string comparisonProperty){_comparisonProperty = comparisonProperty;}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if(value==null) return new ValidationResult("Invalid entry");
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable)) throw new ArgumentException("value has not implemented IComparable interface");
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null) throw new ArgumentException("Comparison property with this name not found");
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if(!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
throw new ArgumentException("The types of the fields to compare are not the same.");
return currentValue.CompareTo((IComparable)comparisonValue) > 0 ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AttributeGreaterThanOrEqual : ValidationAttribute
{
private readonly string _comparisonProperty;
public AttributeGreaterThanOrEqual(string comparisonProperty) { _comparisonProperty = comparisonProperty; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null) return new ValidationResult("Invalid entry");
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable)) throw new ArgumentException("value has not implemented IComparable interface");
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null) throw new ArgumentException("Comparison property with this name not found");
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
throw new ArgumentException("The types of the fields to compare are not the same.");
return currentValue.CompareTo((IComparable)comparisonValue) >= 0 ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AttributeEqual : ValidationAttribute
{
private readonly string _comparisonProperty;
public AttributeEqual(string comparisonProperty) { _comparisonProperty = comparisonProperty; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null) return new ValidationResult("Invalid entry");
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable)) throw new ArgumentException("value has not implemented IComparable interface");
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null) throw new ArgumentException("Comparison property with this name not found");
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
throw new ArgumentException("The types of the fields to compare are not the same.");
return currentValue.CompareTo((IComparable)comparisonValue) == 0 ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AttributeLessThanOrEqual : ValidationAttribute
{
private readonly string _comparisonProperty;
public AttributeLessThanOrEqual(string comparisonProperty) { _comparisonProperty = comparisonProperty; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null) return new ValidationResult("Invalid entry");
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable)) throw new ArgumentException("value has not implemented IComparable interface");
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null) throw new ArgumentException("Comparison property with this name not found");
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
throw new ArgumentException("The types of the fields to compare are not the same.");
return currentValue.CompareTo((IComparable)comparisonValue) <= 0 ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class AttributeLessThan : ValidationAttribute
{
private readonly string _comparisonProperty;
public AttributeLessThan(string comparisonProperty) { _comparisonProperty = comparisonProperty; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == null) return new ValidationResult("Invalid entry");
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable)) throw new ArgumentException("value has not implemented IComparable interface");
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null) throw new ArgumentException("Comparison property with this name not found");
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
throw new ArgumentException("The types of the fields to compare are not the same.");
return currentValue.CompareTo((IComparable)comparisonValue) < 0 ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}
}