Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one do property validation of a C# class using Data Annotations in .NET Framework 3.5?

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?

like image 691
Robert Harvey Avatar asked Jun 24 '13 22:06

Robert Harvey


People also ask

What is property validation?

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.

What is C# validation?

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.

How do you validate data annotations?

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.


2 Answers

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!

like image 120
Patrick Magee Avatar answered Oct 09 '22 23:10

Patrick Magee


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);
        }
    }
like image 25
Mattia Avatar answered Oct 09 '22 23:10

Mattia