31

我的模型中有这两个字段:

[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")],但这仅适用于相等的操作。

我应该为“大于”操作使用什么?

4

3 回答 3

63

看看Fluent ValidationMVC Foolproof Validation:这些对你有很大帮助。

以 Foolproof 为例,[GreaterThan("StartDate")]您可以在 date 属性上使用一个注释。

或者,如果您不想使用其他库,则可以通过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" }
          );
       }
    }
}
于 2013-11-09T20:13:05.973 回答
11

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; 
    }
}
于 2014-05-26T09:35:30.497 回答
3

大量借鉴 Alexander Gore 和 Jaime Marín 在相关 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.
//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);
    }
}

}


于 2018-11-02T17:42:38.027 回答