Building your own custom FluentValidation validator

How to make your own fluent validator for the FluentValidation framework for .NET
July 22 2013

As business app deveopers we all have to write validation code to user input.  My framework of choice for this is the fantastic FluentValidation for .NET.  It provides unit testable validations that do not require the business entity to be valid (if that makes sense! If it doesn't, go read up on it at the previous link).  It also provides fluent API.  

It's common to have to duplicate validation code for business entities.  A good example being a phone number or an address.  Many different busines entities might have both these, eg people, organisations and so on.   It doesn't make sense to use inheritance to only have save on duplication, making the best approach a way to easily repeat the code.  We can either create a simple method that gets used globally, or as I prefer, create an extention method that encapsulates the rules.

In the example below I have to provide validation Provider Numbers, the numbers associated with healthcare professionals in Australia.  My goal is to have my validation code looking this

RuleFor(reg => reg.ProviderNumber).ProviderNumber();

ProviderNumber() contains my validation logic.  To do this I need to provide an extension to IRuleBuilder and create a custom validator.

public static class FluentValidationExtensions
{
	public static IRuleBuilderOptions<T, string> ProviderNumber(this IRuleBuilder<T, string> ruleBuilder)
	{
		return ruleBuilder.SetValidator(new ProviderNumberValidator());
	}
}

The extension method does nothing but provide the fluent api method and the real work is delegated to the custom validator ProviderNumberValidator, which is a simple RegularExpressionValidator.

public class ProviderNumberValidator : RegularExpressionValidator
{
    public ProviderNumberValidator() : base("^[0-9]{6}[0-Z][A-Z]$") { }        
} 

Your own custom validators can be as complex as you need them to be.  Each custom validator needs to inherit from PropertyValidator (or one of it's children and in the case above that is RegularExpressionValidator).  When inheriting directly from PropertyValidator you'll need to place your validation logic in the IsValid method.  In the following example I've created a WebsiteUrlValidator (lets just ignore that it won't validate correctly and just focus on the structure :)).  WebsiteUrlValidator successfully validates all strings that begin with "http://" only.

public class WebsiteUrlValidator : PropertyValidator
{
    public WebsiteUrlValidator() : base("{PropertyName} is not does not start with http://") { }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        var propValue = context.PropertyValue as string;
        if (string.IsNullOrEmpty(propValue) ||
            !propValue.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
            return false;
        return true;
    }
}

Post a comment

comments powered by Disqus