We all have nice business objects at the beginning. However, the codes become bloated, hard to read and maintain after we put in numerous complex business validation logic. We always hope that we can separate main business logic from validation logic, and reuse the validation logic to some degrees.

For example, we use IValidatableObject as the main validation mechanism (self-validating models) in MVC applications.  The validate method will be called after the model binder has assigned values to each of the model properties. There are a few variations. Some use abstract methods, and some use events inside Validate method of the base class to achieve some kinds of separation of main business logic from validation logic.

I came across the small library at github recently, Fluent Validation. This library is the best library that can separate the main business logic from validation logic I can find so far.

The following codes show how to add validation logic  to a customized validator using the popular fluent syntax.

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

The following codes show how to call the validation method.

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

 

Reference:

Fluent Validation