MVC model validation for date
Solution 1:
There is no need to disable jQuery date validation (and that is likely to cause other issues). You just need to override the range
method of the $.validator
.
By default, it works with numeric values (and then falls back to a string comparison), so you can add the following script (after jquery.validate.js
and jquery.validate.unobtrusive.js
, but not wrapped in $(document).ready
$.validator.methods.range = function(value, element, param) {
if ($(element).attr('data-val-date')) {
var min = $(element).attr('data-val-range-min');
var max = $(element).attr('data-val-range-max');
var date = new Date(value).getTime();
var minDate = new Date(min).getTime();
var maxDate = new Date(max).getTime();
return this.optional(element) || (date >= minDate && date <= maxDate);
}
// use the default method
return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
};
Then you can use the RangeAttribute
on your property
[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]
public DateTime Date { get; set; }
Solution 2:
I'd do this with the IValidatableObject
interface from System.ComponentModel.DataAnnotations, which allows you to add extra validation rules where you can do a lot more checking. Add the interface to your class, and then implement the Validate
method, where you can compare the StartDateTime against the current date/time, and also compare the EndDateTime with the StartDateTime, e.g.
public class MyClass : IValidatableObject
{
[Required(ErrorMessage="Start date and time cannot be empty")]
//validate:Must be greater than current date
[DataType(DataType.DateTime)]
public DateTime StartDateTime { get; set; }
[Required(ErrorMessage="End date and time cannot be empty")]
//validate:must be greater than StartDate
[DataType(DataType.DateTime)]
public DateTime EndDateTime { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> results = new List<ValidationResult>();
if (StartDateTime < DateTime.Now)
{
results.Add(new ValidationResult("Start date and time must be greater than current time", new []{"StartDateTime"}));
}
if (EndDateTime <= StartDateTime)
{
results.Add(new ValidationResult("EndDateTime must be greater that StartDateTime", new [] {"EndDateTime"}));
}
return results;
}
}
The only potential drawback to this is that Validate
runs server-side, not in jQuery validation.