DataAnnotation和可选的DateTime值

时间:2011-08-05 17:20:07

标签: c# asp.net asp.net-mvc-3 data-annotations

我正在使用一个接受4个日期的HTML表单,其中两个是可选的。这些日期被插入到MS SQL数据库中,因此我正在边界检查从表单传递的DateTime变量,对SqlDateTime.MinValueSqlDateTime.MaxValue进行检查。这是我的模型的样子:

        [Required]
        [DisplayName("Planned Start Date")]
        [CustomValidation(typeof(Goal), "ValidateGoalDate")]
        public object planned_start_date { get; set; }

        [DisplayName("Actual Start Date")]
        [CustomValidation(typeof(Goal), "ValidateGoalDate")]
        public object start_date { get; set; }

        [Required]
        [DisplayName("Planned End Date")]
        [CustomValidation(typeof(Goal), "ValidateGoalDate")]
        public object planned_end_date { get; set; }

        [DisplayName("Actual Start Date")]
        //[CustomValidation(typeof(Goal), "ValidateGoalDate")]
        public object end_date { get; set; }

我的自定义验证器:

    public static ValidationResult ValidateGoalDate(DateTime goalDate) {

        //* this does not appear to work ever because the optional field does
        //*   not ever get validated.
        if (goalDate == null || goalDate.Date == null)
            return ValidationResult.Success;

        if (goalDate.Date < (DateTime)SqlDateTime.MinValue)
            return new ValidationResult("Date must be after " + SqlDateTime.MinValue.Value.ToShortDateString());

        if (goalDate.Date > (DateTime)SqlDateTime.MaxValue)
            return new ValidationResult("Date must be before " + SqlDateTime.MaxValue.Value.ToShortDateString() );

        return ValidationResult.Success;
    }

每当您提交没有可选值的表单时,就会出现问题。在我的控制器中,我的ModelState.IsValid返回false,我收到验证错误消息:

  

无法通过方法GoalManager.Models.Goal.ValidateGoalDate将“null”类型的值转换为“System.DateTime”。必须输入有效日期。

单步执行代码,我发现自定义验证器不会在可选字段上运行,但是当我从这些可选字段中删除DataAnnotation时,我没有返回任何错误。如果用户没有在字段中插入日期,我想在表中插入NULL。 如何告诉Validator我不想错误检查空白(或空)日期,忽略它,并将空值插入数据库?

3 个答案:

答案 0 :(得分:5)

您的自定义验证程序作为参数使用的DateTime在您的示例中不可为空...如果您使其成为可以为空的DateTime,它应该可以解决您的问题。

答案 1 :(得分:2)

以下是@Rikon所说的实现:

public static ValidationResult ValidateGoalDate(DateTime? goalDate) {

答案 2 :(得分:0)

这将(可能)避免异常,但我想你必须在方法中使用更多代码来跟进它:

public static ValidationResult ValidateGoalDate(DateTime goalDate = new DateTime())

如果ModelState.IsValid返回false仍有问题,可以在控制器中输入这样的内容:

foreach (var state in ModelState) {
    if (state.Key == "start_date") state.Value.Errors.Clear();
}

(我确信有更好的方法可以做到这一点,但没关系,至少这是不言自明的)

顺便说一下,完全禁用验证是不明智的,因为它会启用注入安全漏洞。有关验证的更多信息,以及如何在客户端基于每个字段禁用它,请阅读:http://msdn.microsoft.com/en-us/library/aa479045.aspx#aspplusvalid%5Fclientside