27

I have a Datetime field in my Model and need to validate it so that when it is created it has to fall between Now and 6 Years Prior. I have tried using range like

[Range(DateTime.Now.AddYears(-6), DateTime.Now)]
public DateTime Datetim { get; set; }

But this throws an error cannot convert system datetime to double. Can anyone suggest a workaround to this in the model itself?

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Flood Gravemind
  • 3,773
  • 12
  • 47
  • 79
  • 1
    For anyone using **ASP MVC**, trying client-side validation with `RangeAttribute` for datetime validation you might wanna see this [article](http://stackoverflow.com/questions/21777412/mvc-model-va%E2%80%8C%E2%80%8Blidation-for-date). – Georgi Stoimenov Apr 17 '17 at 14:43
  • what about asp.net webapi ? – Neo Aug 16 '17 at 11:57

3 Answers3

37

Use this attribute:

public class CustomDateAttribute : RangeAttribute
{
  public CustomDateAttribute()
    : base(typeof(DateTime), 
            DateTime.Now.AddYears(-6).ToShortDateString(),
            DateTime.Now.ToShortDateString()) 
  { } 
}
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Ahmed KRAIEM
  • 10,267
  • 4
  • 30
  • 33
  • 2
    To get more beautiful validation message FormatErrorMessage method should be overriden – Lanayx May 21 '15 at 16:05
  • 2
    I know this is old, but how do you use this in the model? – dmikester1 Jun 18 '15 at 13:48
  • 1
    You add it as an attribute(with the code above you would just type [CustomDate] above the property). – master2080 Mar 15 '17 at 14:44
  • Note that ToShortDateString() only includes the Date portion of the DateTime, if you're looking to validate up to now (the second), toString might be better. But also note that this doesn't account for local vs UTC time at all, since it does a comparison to the output of ToString which strips whether it's local or UTC. – IronSean Jan 13 '21 at 15:40
36

Even though there is an overload for Range attribute that accepts type and boundary values of that type and allows something like this:

[Range(typeof(DateTime), "1/1/2011", "1/1/2012", ErrorMessage="Date is out of Range")]

what you are trying to achieve is not possible using this attribute. The problem is that attributes accept only constants as parameters. Obviously neither DateTime.Now nor DateTime.Now.AddYears(-6) are constants.

However you can still do this creating your own validation attribute:

public class DateTimeRangeAttribute : ValidationAttribute
{
    //implementation
}
Andrei
  • 55,890
  • 9
  • 87
  • 108
4

jQuery validation does not work with RangeAttribute, per Rick Anderson. This renders the selected solution incorrect if you're using ASP.NET MVC 5's built-in jQuery validation.

Instead, see the below code from this answer.

public class WithinSixYearsAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        value = (DateTime)value;
        // This assumes inclusivity, i.e. exactly six years ago is okay
        if (DateTime.Now.AddYears(-6).CompareTo(value) <= 0 && DateTime.Now.CompareTo(value) >= 0)
        {
            return ValidationResult.Success;
        }
        else
        {
            return new ValidationResult("Date must be within the last six years!");
        }
    }
}

And it's implemented like any other attribute.

[WithinSixYears]
public DateTime SixYearDate { get; set; }
Sinjai
  • 1,085
  • 1
  • 15
  • 34
  • 2
    The jQuery validation can be easily extended to support date ranges. See https://stackoverflow.com/a/42036626/642287 – Onosa Jan 20 '20 at 14:46