C# 开始日期和结束日期的数据批注

C# 开始日期和结束日期的数据批注,c#,asp.net-mvc-3,data-annotations,C#,Asp.net Mvc 3,Data Annotations,我将视图模型用于开始和结束日期,并使用数据注释进行验证。验证规则包括: 开始日期不应大于结束日期且不为空,为空 结束日期不应小于开始日期且不应小于 DateTime.Now且不为null,为空 以下视图模型由startdate和enddate属性组成。混淆之处在于,如何在以下代码中传递StartEndDateRange数据批注中的EndDate值和EndDate数据批注中的StartDate值: public class StartEndDate { [DataTyp

我将视图模型用于开始和结束日期,并使用数据注释进行验证。验证规则包括:

  • 开始日期不应大于结束日期且不为空,为空
  • 结束日期不应小于开始日期且不应小于 DateTime.Now且不为null,为空
  • 以下视图模型由startdate和enddate属性组成。混淆之处在于,如何在以下代码中传递StartEndDateRange数据批注中的EndDate值和EndDate数据批注中的StartDate值:

      public class StartEndDate
        {
            [DataType(DataType.Date)]
            [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
            [StartEndDateRange("2000/01/01", "value of end date properties")]
            public DateTime StartDate { get; set; }
    
            [DataType(DataType.Date)]
            [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
            [StartEndDateRange("value of startdate properties", DateTime.Now.ToString("yyyy/MM/dd"))]
            public DateTime EndDate { get; set; }
    
    
        }
    
        public class StartEndDateRangeAttribute : ValidationAttribute
        {
            private const string DateFormat = "yyyy/MM/dd";
            private const string DefaultErrorMessage =
         "'{0}' must be a date between {1:d} and {2:d}.";
    
            public DateTime MinDate { get; set; }
            public DateTime MaxDate { get; set; }
    
            public StartEndDateRangeAttribute(string minDate, string maxDate)
                : base(DefaultErrorMessage)
            {
                MinDate = ParseDate(minDate);
                MaxDate = ParseDate(maxDate);
            }
    
            public override bool IsValid(object value)
            {
                if (value == null || !(value is DateTime))
                {
                    return true;
                }
                DateTime dateValue = (DateTime)value;
                return MinDate <= dateValue && dateValue <= MaxDate;
            }
            public override string FormatErrorMessage(string name)
            {
                return String.Format(CultureInfo.CurrentCulture,
         ErrorMessageString,
                    name, MinDate, MaxDate);
            }
    
            private static DateTime ParseDate(string dateValue)
            {
                return DateTime.ParseExact(dateValue, DateFormat,
         CultureInfo.InvariantCulture);
            }
        }
    
    公共类开始日期
    {
    [数据类型(DataType.Date)]
    [DisplayFormat(DataFormatString=“{0:d}”,ApplyFormatInEditMode=true)]
    [StartEndDateRange(“2000/01/01”,“结束日期属性值”)]
    公共日期时间起始日期{get;set;}
    [数据类型(DataType.Date)]
    [DisplayFormat(DataFormatString=“{0:d}”,ApplyFormatInEditMode=true)]
    [StartEndDateRange(“startdate属性的值”,DateTime.Now.ToString(“yyyy/MM/dd”)]
    公共日期时间结束日期{get;set;}
    }
    公共类StartEndDateRangeAttribute:ValidationAttribute
    {
    私有常量字符串DateFormat=“yyyy/MM/dd”;
    私有常量字符串DefaultErrorMessage=
    “{0}必须是介于{1:d}和{2:d}之间的日期。”;
    公共日期时间MinDate{get;set;}
    公共日期时间MaxDate{get;set;}
    公共StartEndDateRangeAttribute(字符串minDate、字符串maxDate)
    :base(DefaultErrorMessage)
    {
    MinDate=ParseDate(MinDate);
    MaxDate=ParseDate(MaxDate);
    }
    公共覆盖布尔值有效(对象值)
    {
    if(值==null | |!(值为DateTime))
    {
    返回true;
    }
    DateTime dateValue=(DateTime)值;
    
    return MinDate在一个验证属性
    DateRange
    中更容易实现这一点


    但是如果您不想这样做,则必须重写
    IsValid(Object,ValidationContext)
    ,从
    ValidationContext.ObjectType
    中提取要验证的对象类型,通过
    ValidationContext.MemberName
    获取其属性,然后从属性中读取值。

    创建两个不同的验证属性。一个是
    DateBefore
    ,另一个是
    DataAfter

    您可以从
    validationContext
    获取验证中模型的属性

    DateBefore
    do中

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
        PropertyInfo endDateProperty= validationContext.ObjectType.GetProperty("EndDate");
        ...
    }
    
    通过以下方式获取值:

    var endDate = endDateProperty.GetValue(validationContext.ObjectInstance, null);
    
    现在比较
    结束日期

    编辑 多一点代码

    public class BeforeEndDateAttribute : ValidationAttribute{
        public string EndDatePropertyName { get; set; }
        public string StartDate { get; set; }
    
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            PropertyInfo endDateProperty = validationContext.ObjectType.GetProperty(EndDatePropertyName);
    
            DateTime endDate = (DateTime) endDateProperty.GetValue(validationContext.ObjectInstance, null);
    
            var startDate = DateTime.Parse(StartDate);
    
            // Do comparison
            // return ValidationResult.Success; // if success
            return new ValidationResult("Error"); // if fail
        }
    
    }
    
    并使用类似于:

    public class MyModel
    {
        [BeforeEndDate(EndDatePropertyName = "EndDate", StartDate = "2000/01/01")]
        public DateTime StartDate { get; set; }
    
        // [AfterStartDate(StartDatePropertyName = "StartDate", EndDate = "2020/01/01")]
        public DateTime EndDate { get; set; }
    }
    

    我可能建议您在类中实现
    IValidatableObject
    ,但唯一的问题是您必须自己进行客户端验证

    public class StartEndDate: IValidatableObject
    {
        [Required]
        public DateTime StartDate { get; set; }
    
        [Required]    
        public DateTime EndDate { get; set; } 
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
           // do the validations
        }
    }
    
    公共类开始日期:IValidatableObject
    {
    [必需]
    公共日期时间起始日期{get;set;}
    [必需]
    公共日期时间结束日期{get;set;}
    公共IEnumerable验证(ValidationContext ValidationContext)
    {
    //进行验证
    }
    }
    
    谢谢,我知道了。但是我必须在dataannotation中为结束日期的值放置什么:
    [StartEndDateRange(“2000/01/01”,“结束日期属性的值”)]
    代替“结束日期属性的值”?没什么。只要
    [StartEndDateRange(“2000/01/01”)]
    。如果需要更多解释,请告诉我。