jungos
jungos

Reputation: 506

DataAnnotation and optional DateTime values

I'm working with a HTML form that accepts 4 dates, two of which are optional. These dates are inserted into a MS SQL database, so I'm boundary checking the DateTime variables, which are passed from the form, against SqlDateTime.MinValue and SqlDateTime.MaxValue. Here's what my model looks like:

        [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; }

And my custom validator:

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

The problem occurs whenever you submit the form without the optional values. In my controller, my ModelState.IsValid returns false and I get a validation error message:

Could not convert the value of type 'null' to 'System.DateTime' as expected by method GoalManager.Models.Goal.ValidateGoalDate. Must enter a valid date.

Stepping though the code, I see that the custom validator does not run on the optional fields, but when I remove the DataAnnotation from those optional fields, I return no error. If the user does not insert a date into the field, I want to insert a NULL into the table. How do tell the Validator that I do not want to error check a blank (or null) date, to ignore it, and to insert a null into the database?

Upvotes: 5

Views: 4945

Answers (3)

Elias
Elias

Reputation: 41

This will (probably) avoid the exception but I guess you have to follow it up with more code inside the method:

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

If you still have a problem with the ModelState.IsValid returning false, you can put something like this in the controller:

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

(I'm sure there are better ways to do this but nevermind, at least this is self-explanatory)

By the way, it is not wise to completely disable validation, as it would enable injection security exploits. For more info on validation, and how you can also disable it on a per-field basis on client-side, read this: http://msdn.microsoft.com/en-us/library/aa479045.aspx#aspplusvalid%5Fclientside

Upvotes: 0

Rick Liddle
Rick Liddle

Reputation: 2714

Here's the implementation of what @Rikon said:

public static ValidationResult ValidateGoalDate(DateTime? goalDate) {

Upvotes: 2

Rikon
Rikon

Reputation: 2696

The DateTime that your custom validator takes as a param is not nullable in your example... If you make it a nullable DateTime, it should fix your problem.

Upvotes: 5

Related Questions