Creating a generic validation framework

Recently in a few discussions of system architecture I have brought up adamant complaints about coupling validation logic to your domain objects. This weekend Thomas Mayfield contacted me on how I would go about implementing this in a domain driven designed system. Initially I got sidetracked over what tool I would use for my rules engine and I’ve still not concluded which would be best so I went about creating my Validation layer and decided to leave the specific details of creating validation logic for later.

As always I start with an interface. In this case it ends up being a very simple interface.

public interface IValidator<T>
{
    ValidationResult Validate(T obj);
    ValidationResult Validate(T obj, bool suppressWarnings);
}

Basically I want this service to take in an object and validate it, and then return to me whether it’s valid and any warnings or error messages associated with the validation. Which lead me to creating a ValidationResult class (in lieu of the similarly named class in the Enterprise Library validation block).

First I created a very simple ValidationMessage class:

public sealed class ValidationMessage
{
    public string Message { get; internal set; }
    public bool Warning { get; internal set; }

    //Only allow creation internally or by ValidationResult class.
    internal ValidationMessage()
    {
    }
}

The ValidationResult class is a little more complex:

public sealed class ValidationResult
{
    private bool _dirty = true;
    private bool _valid;

    public bool Valid
    {
        get
        {
            //theoretically O(n) time but in pratice will be constant time
            //Still, no need for multiple traversals, Traverse only if it's changed
            if (_dirty)
            {
                _valid = Messages.FirstOrDefault(msg => msg.Warning == false) == null;
                _dirty = false;
            }

            return _valid;
        }
    }

    public ValidationResult()
    {
        Messages = new List<ValidationMessage>();
    }

    public IList<ValidationMessage> Messages { get; internal set; }

    /// <summary>
    /// Adds the error. 
    /// </summary>
    /// <param name="errorMessage">The error message.</param>
    public void AddError(string errorMessage)
    {
        _dirty = true;
        Messages.Add(new ValidationMessage {Message = errorMessage});
    }

    /// <summary>
    /// Adds the warning. 
    /// </summary>
    /// <param name="warningMessage">The warning message.</param>
    public void AddWarning(string warningMessage)
    {
        //No need to mark collection dirty since warnings never generate validation changes
        Messages.Add(new ValidationMessage {Message = warningMessage, Warning = true});
    }
}

Basically the only tricks to this class is that I only allow the creation of the internal list of ValidationMessages to be handled by the same assembly. I also appended factory methods to allow manual insertion of errors or warnings. The reason for this is in my workings with EntLib VAB was that the results were inflexible in letting me append some messages myself and then roll the results down to the screen. This resulted in me having to create marshaling classes to just transfer the messages from the results to a collection that I could add more information to.

Implementing a concrete validator, the EmployeeValidator:

public class EmployeeValidator : IValidator<Employee>
{
    #region Implementation of IValidation<Employee>

    public ValidationResult Validate(Employee employee)
    {
        return Validate(employee, false);
    }

    public ValidationResult Validate(Employee employee, bool suppressWarnings)
    {
        var result = new ValidationResult();

        //This code here would be replaced with a validation rules engine later

        if (employee != null)
        {
            if (!suppressWarnings && employee.HireDate > DateTime.Now)
                result.Messages.Add(new ValidationMessage {
                    Message = string.Format("Employee hire date: {0} is set in the future.", employee.HireDate),
                    Warning = true});

            if (employee.Person != null)
            {
                if (string.IsNullOrEmpty(employee.Person.FirstName))
                    result.Messages.Add(new ValidationMessage {Message = "Employee FirstName is required."});
                if (string.IsNullOrEmpty(employee.Person.LastName))
                    result.Messages.Add(new ValidationMessage {Message = "Employee LastName is required."});
            }
            else
                result.Messages.Add(new ValidationMessage {Message = "Employee person data is missing."});
        }
        else
            result.Messages.Add(new ValidationMessage {Message = "Employee data is missing."});

        return result;
    }

    #endregion
}

Nothing really complicated goes on here just simple very basic validation code that rolls in error messages if needed. This area here would be replaced by a ruleset engine later on, for myself atleast. Otherwise you could do any validation you wanted here.

Now to actually validate your objects I created a ValidationFactory method also simliar to the VAB.

public static class ValidationFactory
{
    public static ValidationResult Validate<T>(T obj)
    {
        try
        {
            var validator = ObjectFactory.GetInstance<IValidator<T>>();
            return validator.Validate(obj);
        }
        catch (Exception ex)
        {
            var messages = new List<ValidationMessage> {new ValidationMessage {
                Message = string.Format("Error validating {0}", obj)}};

            messages.AddRange(FlattenError(ex));

            var result = new ValidationResult {Messages = messages};
            return result;
        }
    }

    private static IEnumerable<ValidationMessage> FlattenError(Exception exception)
    {
        var messages = new List<ValidationMessage>();
        var currentException = exception;

        do
        {
            messages.Add(new ValidationMessage {Message = exception.Message});
            currentException = currentException.InnerException;
        } while (currentException != null);

        return messages;
    }
}

Once again beauty comes with simplicity I take advantage of StructureMap to handle my dependency injection with the GetInstance method. Then just call Validate. I added a helper method that will allow me to roll out a complex exception message (most likely it’d only ever be you forgot to register a validator for some type) if any occur.

Registering this for StructureMap is extremely simple inside you registry setup for SM you would just add

ForRequestedType<IValidator<Employee>>().TheDefaultIsConcreteType<EmployeeValidator>();

And then onto a quick usage example

[Test]
public void InvalidEmployeeTest()
{
    var employee = new Employee {Person = new Person {FirstName = string.Empty, LastName = string.Empty}};

    var results = ValidationFactory.Validate(employee);

    Assert.IsNotNull(results);
    Assert.IsFalse(results.Valid);
    Assert.IsTrue(results.Messages.Count > 0);
}

At this point you have en entirely decoupled validation framework that will allow you to validate your objects with any kit, ruleset engine, or static validation you wish. Now if you wondered where I would put this in my architecture I would have it validate at the presenter level right after the screen scrape of data.

public bool SaveEmployee()
{
    var employee = View.Employee;

    var results = ValidationFactory.Validate(employee);

    if (results.Valid)
        _controller.SaveEmployee(employee);
    else
        View.Errors = results.Messages;
}

kick it on DotNetKicks.com

Shout it

BloggingContext.ApplicationInstance.CompleteRequest();