Introduction
In the .NET Framework 4, a namespace called System.ComponentModel.DataAnnotations
is available for both the common CLR (WPF) and the lighter Silverlight CLR. You can use the DataAnnotations
namespace for various purposes. One of these is for data validation using attributes, and another is the visual description of fields, properties, and methods, or to customize the data type of a specific property. These three categories are classified in the .NET Framework as Validation Attributes, Display Attributes, and Data Modeling Attributes. This section uses Validation Attributes to define validation rules for objects
Using the Code
To use the DataAnnotations
namespace, you need to add a reference to the assembly—that reference is not included in any Visual Studio project template by default. Then you need to decorate your objects with the correct attributes. As an example, the code below uses an incorrect approach of decorating a Domain Entity directly with these attributes. Next, I will refactor this code to make that entity unaware of its validation.
public sealed class Customer
{
[Required(ErrorMessage = "The FirstName is a mandatory Field")]
[StringLength(10, ErrorMessage =
"The FirstName should be greater than 10 characters.")]
public string FirstName { get; set; }
[Required(ErrorMessage = "The LastName is a mandatory Field")]
[StringLength(10, ErrorMessage =
"The LastName should be greater than 10 characters.")]
public string LastName { get; set; }
[Required(ErrorMessage = "The Title is a mandatory Field")]
public string Title { get; set; }
}
The Customer
entity can be easily validated using a generic validator because you know that we want to validate only those properties that have a DataAnnotations
attribute on them.
public sealed class GenericValidator<T>
{
public IList<ValidationResult> Validate(T entity)
{
var results = new List<ValidationResult>();
var context = new ValidationContext(entity, null, null);
Validator.TryValidateObject(entity, context, results);
return results;
}
}
At this point, we can easily test the validator against the Customer
entity, as follows:
[TestMethod]
public void CanValidateCustomer()
{
Customer entity = new Customer { FirstName = "", LastName = "" };
GenericValidator<Customer> target = new GenericValidator<Customer>();
bool expected = false;
bool actual;
actual = target.Validate(entity).Count == 0;
Assert.AreEqual(expected, actual,
"The Entity should not be valid at this point.");
}
Refactor your Code – Good Approach
Now, to remove the validation from the Domain Entity, you need to create an interface that represents the Domain Entity and that includes the validation rules, and then inherit the Domain Entity from this interface. At the end of this process, you should be able to write code like this:
[TestMethod]
public void CanValidateCustomer()
{
Customer entity = new Customer { FirstName = "", LastName = "" };
GenericValidator<ICustomer> target = new GenericValidator<ICustomer>();
bool expected = false;
bool actual;
actual = target.Validate(entity).Count == 0;
Assert.AreEqual(expected, actual,
"The Entity should not be valid at this point.");
}
Available Validation Frameworks
The validation technique that was just presented is only one of the techniques available for .NET. The advantage of using DataAnnotations
is that it plugs into WPF and Silverlight perfectly, and it is designed in a way that works throughout all the layers of an MVVM application. In the ViewModel
section, you’ll see why the DataAnnotations
approach is the perfect match for WPF or Silverlight.
Another interesting framework created by Microsoft is the Validation Application Block, which is available with Microsoft Enterprise Library 5.0 (http://entlib.codeplex.com/). The Validation Application Block uses the same general approach—validating an object against a set of rules defined using attributes (data annotations) or an external XML file. The major difference from the DataAnnotations
is the process you use to validate an object, but you should obtain the same final result.
Another framework, part of the open-source project NHibernate, is the NHibernate Validation Framework. This is available at http://sourceforge.net/projects/nhcontrib/ as part of the NHibernate Contrib project. The main disadvantage of using this framework is that unless you are planning to use NHibernate as your O/RM, you will introduce an additional dependency in your layers that might not be needed. This framework also requires you to sully your entities with validation rules related to a specific O/RM.
References
Summary
To sum up, it’s important to keep the Domain clean and unaware of the validation rules or methods you’re using, but it’s also important that you decide to use the appropriate framework for the type of application that you’re writing.
History
- 22nd April, 2011: Initial version
- 18th May, 2011: Updated References section
- 16th June, 2011: Updated code