Stephen A. Fuqua (SAF) is a Bahá'í, software developer, and conservation and interfaith advocate in the DFW area of Texas.

Some Tips for Use of DataAnnotations in .Net

June 27, 2012

Wherein I record a few tips on the use of System.ComponentModel.DataAnnotations, which I am likely to forget if I do not need to think about them again for some months…

[validator screenshot from MSDN]

Unit Testing for Validation Attributes

In your unit tests, do not test the validation – but rather test to see if the validation attributes have been applied. See Brad Wilson's blog post, DataAnnotations and ASP.NET MVC, for details.

Manual Validation

If you do manually validate, in a unit test or production code, using Validator.TryValidateObject (or other methods in the Validator class), then be sure to set the validateAllProperties = true. By default it is false and that means that only Required properties will be validated. <editorial>Why in the world is this false by default? The obvious and expected behavior is that all properties would be validated</editorial>. Validator.TryValidateObject(someObject, new ValidationContext(someObject, null, null), resultList, true).

Validating Related Objects

Validating inherited fields works nicely. But what about composition / delegation? If you are validating object A, and it is composed of objects B and C that are also validated, then you need some "deep" validation. There is a simple recipe for accomplishing this:

  1. Implement IValidatableObject on class A, which will require you to add a method with signature public IEnumerable Validate(ValidationContext validationContext).
  2. Set this method to run TryValidateObject on the instance of B and of C. Each call to TryValidateObject will need its own ValidationContext. Constructing a ValidationContext is simple – just pass in the object itself, and generally it is appropriate to pass null for the second and third parameter. Don't forget to throw in a true for validating all properties! Something like this will work (with opportunity for multiple refactorings):
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var resultList = new List<ValidationResult>();
    
        Validator.TryValidateObject(this.InstanceOfB, new ValidationContext(this.InstanceOfB, null, null), resultList, true);
        Validator.TryValidateObject(this.InstanceOfC, new ValidationContext(this.InstanceOfC, null, null), resultList, true);
    
        return resultList;
    }
    

    Now, you wrote a failing unit test for this Validate method before coding it, right?

Caution: if any of the properties directly in A are invalid, then those will be detected and Validate(ValidationContext validationContext) will never be called.

Validation Summary in an MVC Partial View

When using partial views for AJAX support in an MVC application, a @Html.ValidationSummary() should be put inside the partial view. If you put it inside the hosting view, then it will not be populated when you submit a form inside the partial view.

No TrackBacks

TrackBack URL: http://www.safnet.com/fcgi-bin/mt/mt-tb.cgi/80

Leave a comment