モデルには次の2つのフィールドがあります。
_[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")]
を使用してみましたが、これは等しい操作に対してのみ機能します。
「より大きい」操作には何を使用すればよいですか?
Fluent Validation または MVC Foolproof Validation をご覧ください。これらは非常に役立ちます。
たとえば、フールプルーフでは、日付プロパティで使用できる[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" });
}
}
}
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;
}
}
関連するStackOverflow質問でのAlexander GoreとJaimeMarínの回答から大きく借りて、 1 を使用して、GT、GE、EQ、LE、およびLT演算子(IComparableを実装している場合)。そのため、たとえば、日付、時刻、整数、文字列のペアに使用できます。
これらすべてを1つのクラスにマージし、演算子を引数として取るのは良いことですが、その方法はわかりません。 3つの例外をそのまま残しました。スローされた場合、ユーザー入力の問題ではなく、実際にフォーム設計の問題を表しているからです。
このようにモデルで使用するだけで、5つのクラスを持つファイルは次のようになります。
[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.
//https://stackoverflow.com/questions/41900485/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);
}
}
}