Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET MVC Custom Date Validator

I'll be tackling writing a custom date validation class tomorrow for a meeting app i'm working on at work that will validate if a given start or end date is A) less than the current date, or B) the start date is greater than the end date of the meeting (or vice versa).

I think this is probably a fairly common requirement. Can anyone point me in the direction of a blog post that might help me out in tackling this problem?

I'm using .net 3.5 so i can't use the new model validator api built into .NET 4. THe project i'm working on is MVC 2.

UPDATE: THe class i'm writing needs to extend the System.ComponentModel.DataAnnotations namespace. In .NET 4 there is a IValidateObject interface that you can implement, that makes this sort of thing an absolute doddle, but sadly i can't use .Net 4. How do i go about doing the same thing in .Net 3.5?

like image 582
MrBliz Avatar asked Aug 31 '10 23:08

MrBliz


2 Answers

public sealed class DateStartAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        DateTime dateStart = (DateTime)value;
        // Meeting must start in the future time.
        return (dateStart > DateTime.Now);
    }
}

public sealed class DateEndAttribute : ValidationAttribute
{
    public string DateStartProperty { get; set; }
    public override bool IsValid(object value)
    {
        // Get Value of the DateStart property
        string dateStartString = HttpContext.Current.Request[DateStartProperty];
        DateTime dateEnd = (DateTime)value;
        DateTime dateStart = DateTime.Parse(dateStartString);

        // Meeting start time must be before the end time
        return dateStart < dateEnd;
    }
}

and in your View Model:

[DateStart]
public DateTime StartDate{ get; set; }

[DateEnd(DateStartProperty="StartDate")]
public DateTime EndDate{ get; set; }

In your action, just check that ModelState.IsValid. That what you're after?

like image 102
just.jimmy Avatar answered Sep 29 '22 01:09

just.jimmy


I know this post is older, but, this solution I found is much better.

The accepted solution in this post won't work if the object has a prefix when it is part of a viewmodel.

i.e. the lines

// Get Value of the DateStart property
string dateStartString = HttpContext.Current.Request[DateStartProperty];

A better solution can be found here: ASP .NET MVC 3 Validation using Custom DataAnnotation Attribute:

New DateGreaterThan attribute:

public sealed class DateGreaterThanAttribute : ValidationAttribute
{
    private const string _defaultErrorMessage = "'{0}' must be greater than '{1}'";
    private string _basePropertyName;

    public DateGreaterThanAttribute(string basePropertyName) : base(_defaultErrorMessage)
    {
        _basePropertyName = basePropertyName;
    }

    //Override default FormatErrorMessage Method
    public override string FormatErrorMessage(string name)
    {
        return string.Format(_defaultErrorMessage, name, _basePropertyName);
    }

    //Override IsValid
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        //Get PropertyInfo Object
        var basePropertyInfo = validationContext.ObjectType.GetProperty(_basePropertyName);

        //Get Value of the property
        var startDate = (DateTime)basePropertyInfo.GetValue(validationContext.ObjectInstance, null);

        var thisDate = (DateTime)value;

        //Actual comparision
        if (thisDate <= startDate)
        {
            var message = FormatErrorMessage(validationContext.DisplayName);
            return new ValidationResult(message);
        }

        //Default return - This means there were no validation error
        return null;
    }
}

Usage example:

[Required]
[DataType(DataType.DateTime)]
[Display(Name = "StartDate")]
public DateTime StartDate { get; set; }

[Required]
[DataType(DataType.DateTime)]
[Display(Name = "EndDate")]
[DateGreaterThanAttribute("StartDate")]
public DateTime EndDate { get; set; }
like image 31
matty_simms Avatar answered Sep 29 '22 02:09

matty_simms