I have a ViewModel for my MVC4 Prject containing two DateTime properties:
[Required]
[DataType(DataType.Date)]
public DateTime RentDate { get; set; }
[Required]
Here is a very quick basic implementation (without error checking etc.) that should do what you ask (only on server side...it will not do asp.net client side javascript validation). I haven't tested it, but should be enough to get you started.
using System;
using System.ComponentModel.DataAnnotations;
namespace Test
{
[AttributeUsage(AttributeTargets.Property)]
public class DateGreaterThanAttribute : ValidationAttribute
{
public DateGreaterThanAttribute(string dateToCompareToFieldName)
{
DateToCompareToFieldName = dateToCompareToFieldName;
}
private string DateToCompareToFieldName { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
DateTime earlierDate = (DateTime)value;
DateTime laterDate = (DateTime)validationContext.ObjectType.GetProperty(DateToCompareToFieldName).GetValue(validationContext.ObjectInstance, null);
if (laterDate > earlierDate)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult("Date is not later");
}
}
}
public class TestClass
{
[DateGreaterThan("ReturnDate")]
public DateTime RentDate { get; set; }
public DateTime ReturnDate { get; set; }
}
}
Not sure of it's use in MVC/Razor, but..
You can use DateTime.Compare(t1, t2) - t1 and t2 being the times you want to compare. It will return either -1, 0 or 1 depending on what the results are.
Read more here: http://msdn.microsoft.com/en-us/library/system.datetime.compare.aspx
It looks like you're using DataAnnotations so another alternative is to implement IValidatableObject
in the view model:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.RentDate > this.ReturnDate)
{
yield return new ValidationResult("Rent date must be prior to return date", new[] { "RentDate" });
}
}
If you're using .Net Framework 3.0 or higher you could do it as a class extension...
/// <summary>
/// Determines if a <code>DateTime</code> falls before another <code>DateTime</code> (inclusive)
/// </summary>
/// <param name="dt">The <code>DateTime</code> being tested</param>
/// <param name="compare">The <code>DateTime</code> used for the comparison</param>
/// <returns><code>bool</code></returns>
public static bool isBefore(this DateTime dt, DateTime compare)
{
return dt.Ticks <= compare.Ticks;
}
/// <summary>
/// Determines if a <code>DateTime</code> falls after another <code>DateTime</code> (inclusive)
/// </summary>
/// <param name="dt">The <code>DateTime</code> being tested</param>
/// <param name="compare">The <code>DateTime</code> used for the comparison</param>
/// <returns><code>bool</code></returns>
public static bool isAfter(this DateTime dt, DateTime compare)
{
return dt.Ticks >= compare.Ticks;
}
Nothing like that exists in the framework. A common similar attribute is the RequiredIf
. It is described in this post.
RequiredIf Conditional Validation Attribute
Model:
[DateCorrectRange(ValidateStartDate = true, ErrorMessage = "Start date shouldn't be older than the current date")]
public DateTime StartDate { get; set; }
[DateCorrectRange(ValidateEndDate = true, ErrorMessage = "End date can't be younger than start date")]
public DateTime EndDate { get; set; }
Attribute class:
[AttributeUsage(AttributeTargets.Property)]
public class DateCorrectRangeAttribute : ValidationAttribute
{
public bool ValidateStartDate { get; set; }
public bool ValidateEndDate { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var model = validationContext.ObjectInstance as YourModelType;
if (model != null)
{
if (model.StartDate > model.EndDate && ValidateEndDate
|| model.StartDate > DateTime.Now.Date && ValidateStartDate)
{
return new ValidationResult(string.Empty);
}
}
return ValidationResult.Success;
}
}