Monday, November 14, 2011

Custom validation using MVC3 ValidationAttribute

In this Demo, Let's create a custom validation attribute "DateGreaterAttribute" that validates that a Template EndDate is later than the given StartDate. This validation attribute will be applied like any other Data Annotations.



public partial class Template
{
public Template()
{
}

public int TemplateId { get; set; }
public string Name { get; set; }
public byte Active { get; set; }
public System.DateTime Effective { get; set; }
[DateGreater(DateStartProperty="Effective", ErrorMessage="The Expiration Date must be after the Effective Date")]
public Nullable Expiring { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public int ChangedBy { get; set; }
public System.DateTime ChangedAt { get; set; }

}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DateGreaterAttribute : ValidationAttribute
{
public DateGreaterAttribute() : base("The End Date must be later then Start Date")
{
}
public string DateStartProperty { get; set; }

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string dateEndString = (value != null) ? value.ToString() : string.Empty;
if (string.IsNullOrWhiteSpace(dateEndString))
{
// A blank end date means no comparison. Use Required attribute to force an end date entry.
return ValidationResult.Success;
}

// Get the start date and compare to the end date
bool valid = false;
PropertyInfo dateStartPropertyInfo = validationContext.ObjectType.GetProperty (DateStartProperty);

if (dateStartPropertyInfo != null)
{
object dateStartValue = dateStartPropertyInfo.GetValue(validationContext.ObjectInstance, null);
string dateStartString = (dateStartValue != null) ? dateStartValue.ToString() : string.Empty;
DateTime dateStart;

if (DateTime.TryParse(dateStartString, out dateStart))
{
DateTime dateEnd;
if (DateTime.TryParse(dateEndString, out dateEnd))
{
valid = (dateStart < dateEnd);
}
}
}

return valid ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}



In the above code, we are implementing a class initializer and IsValid() from the base class. The constructor allows you to provide a default error message in case of validation failure.
The IsValid() method provides 2 parameters,
1. object value - It's the value entered by the user for End Date field.
2. validationContext - Describes the context in which a validation check is performed. The 2 important property that we use here are -
a) ObjectType - Get the type of the object to validate i.e. Template. The GetProperty()method provided by it, returns property information on the Start Date parameter.
b) ObjectInstance - Get the object to validate i.e. Template. This instance is used to get the value of Start Date parameter.

No comments:

Post a Comment