TOC

The community is working on translating this tutorial into French, but it seems that no one has started the translation process for this article yet. If you can help us, then please click "More info".

Models:

Manual Model validation with Data Annotations

When using Model validation with Data Annotations, the MVC framework will usually handle most of the process of performing the actual validation and even presenting the results to the end-user in the way you want it. However, as we already talked about, a cool thing about the MVC pattern is the separation of concerns. This means that while you may build a nice collection of Models to represent all the data of your web application, these Models can also be used outside of the MVC framework, e.g. in a desktop application. How is that possible? Because Models are just regular .NET classes!

But why would you ever need to use your Models outside the MVC framework? Well, there's a good chance that you won't - it really depends on what you're working on. But as an example, consider a larger project where you need to automate some actions and run them directly from the command line instead of through the webserver. This will allow you to schedule these actions through the Windows Task Scheduler (or as a cron job on *nix), without having to worry about timeouts and other web-related limitations.

In a case like that, you can easily re-use your Models in another type of application, e.g. a Console App - just add a reference to the Project where you keep your Models (which can be a separate project or part of your Web project) and start using the Model classes just like any other class. This is awesome, but what about validation? Since the MVC framework handles a lot of the "magic" involved in performing the actual validation, it's not quite clear how to take advantage of the validation rules you have added to your Models using Data Annotations.

Performing a manual Model validation

Let me demonstrate how to accomplish this. We have the WebUser Model which we used in previous examples in this chapter:

public class WebUser
{
    [Required]
    [StringLength(25)]
    public string FirstName { get; set; }

    [Required]
    [StringLength(50, MinimumLength = 3)]
    public string LastName { get; set; }

    [Required]
    [EmailAddress]
    public string MailAddress { get; set; }
}

As you can see, its properties have been nicely decorated with validation annotations, specifying the various requirements - these rules are what we are looking to take advantage of outside of the MVC application. Therefore I have created, within the same Solution, a Console App project to demonstrate this. Obviously, this is just to demonstrate an alternative use-case for these mechanisms - you may use the same approach within your MVC applications in case you want more control over the validation process for some reason. Here's our Console App:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using WebApp.Models;

namespace TaskRunner
{
    class Program
    {
static void Main(string[] args)
{
    Console.WriteLine("Starting validation:");

    WebUser user = new WebUser();
    user.FirstName = null;
    user.LastName = "aa";
    user.MailAddress = "blah@blah@blah";

    var context = new ValidationContext(user, null, null);
    var results = new List<ValidationResult>();

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

    if(!isValid)
    {
Console.WriteLine("User is NOT valid! Errors:");
foreach(var validationResult in results)
{
    Console.WriteLine(validationResult.ErrorMessage);
}
    }
    Console.WriteLine("Done...");
    Console.ReadKey();
}
    }
}

What we do here is pretty simple. I create a new WebUser object and then I deliberately assign invalid values to it, to test the validation. We then create a ValidationContext, based on the WebUser object, as well as a List for holding the ValidationResult return values. The most interesting line is where we call the Validatior.TryValidateObject() method. It will validate the WebUser object (first parameter), using the ValidationContext (second parameter) and assign the result to the results variable (third parameter). The fourth parameter specifies that ALL properties should be validated, not just the Required ones. The Console output will look like this:

Starting validation:
User is NOT valid! Errors:
The FirstName field is required.
The field LastName must be a string with a minimum length of 3 and a maximum length of 50.
The MailAddress field is not a valid e-mail address.
Done...

Summary

Using just a few lines of code, we can take advantage of the validation rules specified on your Models using Data Annotations and validate Models wherever we want to and do whatever we want to with the results. This can come in handy in several situations, e.g. when you want to re-use the validation rules outside of the MVC framework or when you want full control of the validation process.