Manual Validation with Data Annotations

Several people have asked me about using data annotations for validation outside of a UI framework, like ASP.NET MVC or Silverlight. The System.ComponentModel.DataAnnotations assembly contains everything you need to execute validation logic in the annotations. Specifically, there is a static Validator class to execute the validation rules. For example, let's say you have the following class in a console mode application:

public class Recipe
{
    [Required]
    public string Name { get; set; } 
}

You could validate the recipe with the following code:

var recipe = new Recipe();
var context = new ValidationContext(recipe, serviceProvider: null, items: null);
var results = new List<ValidationResult>();

var isValid = Validator.TryValidateObject(recipe, context, results);

if (!isValid)
{
    foreach (var validationResult in results)
    {
        Console.WriteLine(validationResult.ErrorMessage);
    }
}

Result: "The Name field is required".

You can construct the ValidationContext class without a service provider or items collection, as shown in the above code, as they are optional for the built-in validation attributes. The Validator also executes any custom attributes you have defined, and for custom attributes you might find the serviceProvider useful as a service locator, while the items parameter is a dictionary of extra data to pass along. The Validator also works with self validating objects that implement IValidatableObject.

public class Recipe : IValidatableObject 
{
    [Required]
    public string Name { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // ...
    }
}

Like everything framework related, the Validator tries to provide an API that will work in a number of validation scenarios. I recommend you bend it to your will and build something that makes it easy to use inside your specific design and architecture. A class like the following would be a step towards hiding some complexity.

public class DataAnnotationsValidator
{
    public bool TryValidate(object @object, out ICollection<ValidationResult> results)
    {
        var context = new ValidationContext(@object, serviceProvider: null, items: null);
        results = new List<ValidationResult>();
        return Validator.TryValidateObject(
            @object, context, results, 
            validateAllProperties: true
        );
    }
}

Print | posted @ Wednesday, June 29, 2011 9:12 PM

Comments on this entry:

Gravatar # re: Manual Validation with Data Annotations
by Johan at 6/30/2011 3:25 AM

Sweet! Very useful!
  
Gravatar # re: Manual Validation with Data Annotations
by Prashant Brall at 6/30/2011 4:50 AM

Very nice, short and simple :)
  
Gravatar # re: Manual Validation with Data Annotations
by Zukki at 7/1/2011 5:12 AM

thanks Scott, your Master Pages: Tips, Tricks, and Traps article was a big help for me, your blog is on my favorites now!
  
Gravatar # re: Manual Validation with Data Annotations
by rtpHarry at 7/1/2011 5:52 AM

Scott, correct me if I'm wrong but shouldn't this line: var isValid = Validator.TryValidateObject(recipe, context, results); have an out keyword on the results parameter?
  
Gravatar # re: Manual Validation with Data Annotations
by rtpHarry at 7/1/2011 6:56 AM

I will correct myself :) No, it doesn't have an out. http://msdn.microsoft.com/en-us/library/dd411772(v=VS.100).aspx
  
Gravatar # re: Manual Validation with Data Annotations
by Thanigainathan at 7/4/2011 3:41 AM

Hi,

Thanks for sharing this usefuk info
  
Gravatar # re: Manual Validation with Data Annotations
by Yann at 7/15/2011 12:33 AM

Worth mentioning that the Validator class from the Data Annotations namespace doesn't validate your object recursively but only top properties data attributes.
If some of your properties are complex types for which you've set data annotations attributes, validation will not run.

It can quite easily be done using reflection with recursion though.
  
Gravatar # re: Manual Validation with Data Annotations
by Scott at 7/18/2011 7:20 PM

If the name property had some metadata, like [DisplayName("FullName")], you'd still get the error message "The Name field is required." Any idea how to get validation to pay attention to System.ComponentModel metadata in this scenario?
  
Gravatar # re: Manual Validation with Data Annotations
by scott at 7/18/2011 10:11 PM

@scott: Use [Display(Name="...")] instead. That one should work.
  
Gravatar # re: Manual Validation with Data Annotations
by EHA at 8/2/2011 7:39 AM

Have you tested you code yourself.. ? It doesn't work..
  
Gravatar # re: Manual Validation with Data Annotations
by scott at 8/2/2011 7:48 AM

@EHA: I tested the code.
  
Gravatar # re: Manual Validation with Data Annotations
by James William at 8/5/2011 3:30 AM

A nice way to validate. Great article
  
Comments have been closed on this topic.