Reputation: 506
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
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
Reputation: 2714
Here's the implementation of what @Rikon said:
public static ValidationResult ValidateGoalDate(DateTime? goalDate) {
Upvotes: 2
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