web-dev-qa-db-ja.com

mvc4データ注釈は2つの日付を比較します

モデルには次の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; }
_

endDatestartDateより大きくなければなりません。 [Compare("startDate")]を使用してみましたが、これは等しい操作に対してのみ機能します。

「より大きい」操作には何を使用すればよいですか?

29
user2208349

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" });
       }
    }
}
57
Davor Zlotrg

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; 
    }
}
11
Mahbub

関連する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);
    }
}

}


2