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…
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:
- Implement
IValidatableObject
on class A, which will require you to add a method with signaturepublic IEnumerable
.Validate(ValidationContext validationContext) -
Set this method to run
TryValidateObject
on the instance of B and of C. Each call toTryValidateObject
will need its ownValidationContext
. Constructing aValidationContext
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 atrue
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