Is there a way in the .NET Framework to hand some method or validator an object instance whose class is decorated with Data Annotations, and receive a collection of errors?
I see that there is a way to do this in .NET 4.x. But is there a similar mechanism in .NET 3.5?
To validate a property or a page means to check its value against certain rules, and add a message to the page if validation fails.
The validation attributes specify behavior that you want to enforce on the model properties they are applied to. The Required attribute indicates that a property must have a value; in this sample, a movie has to have values for the Title , ReleaseDate , Genre , and Price properties in order to be valid.
DataAnnotations namespace includes the following validator attributes: Range – Enables you to validate whether the value of a property falls between a specified range of values. RegularExpression – Enables you to validate whether the value of a property matches a specified regular expression pattern.
With a bit of reflection, you could build your own validator which scans the ValidationAttributes
on the properties you have. It may not be a perfect solution, but if you're limited to using .NET 3.5, this seems like a lightweight solution, hopefully you get the picture.
static void Main(string[] args)
{
Person p = new Person();
p.Age = 4;
var results = Validator.Validate(p);
results.ToList().ForEach(error => Console.WriteLine(error));
Console.Read();
}
// Simple Validator class
public static class Validator
{
// This could return a ValidationResult object etc
public static IEnumerable<string> Validate(object o)
{
Type type = o.GetType();
PropertyInfo[] properties = type.GetProperties();
Type attrType = typeof (ValidationAttribute);
foreach (var propertyInfo in properties)
{
object[] customAttributes = propertyInfo.GetCustomAttributes(attrType, inherit: true);
foreach (var customAttribute in customAttributes)
{
var validationAttribute = (ValidationAttribute)customAttribute;
bool isValid = validationAttribute.IsValid(propertyInfo.GetValue(o, BindingFlags.GetProperty, null, null, null));
if (!isValid)
{
yield return validationAttribute.ErrorMessage;
}
}
}
}
}
public class Person
{
[Required(ErrorMessage = "Name is required!")]
public string Name { get; set; }
[Range(5, 20, ErrorMessage = "Must be between 5 and 20!")]
public int Age { get; set; }
}
This prints out the following to the Console:
Name is required!
Must be between 5 and 20!
Linq Version
public static class Validator
{
public static IEnumerable<string> Validate(object o)
{
return TypeDescriptor
.GetProperties(o.GetType())
.Cast<PropertyDescriptor>()
.SelectMany(pd => pd.Attributes.OfType<ValidationAttribute>()
.Where(va => !va.IsValid(pd.GetValue(o))))
.Select(xx => xx.ErrorMessage);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With