Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

Validation in .NET Framework 4

4.27/5 (7 votes)
18 Jun 2011CPOL3 min read 67.3K   788  
Validation Frameworks in .NET Framework 4

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.

C#
public sealed class Customer
{
    /// <summary>
    /// Gets or sets the first name.
    /// </summary>
    /// <value>The first name.</value>
    [Required(ErrorMessage = "The FirstName is a mandatory Field")]
    [StringLength(10, ErrorMessage = 
	"The FirstName should be greater than 10 characters.")]
    public string FirstName { get; set; }

    /// <summary>
    /// Gets or sets the last name.
    /// </summary>
    /// <value>The last name.</value>
     [Required(ErrorMessage = "The LastName is a mandatory Field")]
    [StringLength(10, ErrorMessage = 
	"The LastName should be greater than 10 characters.")]
    public string LastName { get; set; }

    /// <summary>
    /// Gets or sets the title.
    /// </summary>
    /// <value>The title.</value>
    [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.

C#
public sealed class GenericValidator<T>
{
    /// <summary>
    /// Validates the specified entity.
    /// </summary>
    /// <param name="entity">The entity.</param>
    /// <returns></returns>
    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:

C#
/// <summary>
/// Determines whether this instance [can validate customer].
/// </summary>
[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:

C#
/// <summary>
/// Determines whether this instance [can validate customer].
/// </summary>
[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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)