To use for a web based mvc3 .net application, which validation framework would you recommend? Application follows domain model pattern and domain models POCOs are in separate class library?
The sort of validation that will be required will be... Not Null, Regular Expression based etc
I would go with FluentValidation, it's an awesome open source project
https://github.com/JeremySkinner/FluentValidation
It's equally good for basic and more complex validations
If you need a list of failures (and not one at a time exceptions), then I like the Enterprise Library Validation block.
See the powerpoint presentation at:
http://msdn.microsoft.com/en-us/library/ff650484.aspx
You can wire up most basic validations against your POCO objects.
And alot of the pre-fab rules can be setup in a .config file.
And you can write your own rules.
My rules are very granular. They perform 1 validation at a time.
As a simple example: I would have 2 different rules to decide if an employee is hireable (based on birthdate).
One rule would make sure the birthdate of the employee was specified.
A second rule would make sure that the current-date minus the birth-date was greater than 18 years. (or whatever the rule was).
(Now let's assume I have a bunch of rules into place).
So after the validation routines run, I get back a list of all (invalid) situations in a list. For example, if I were validating an employee, I would get a list of invalids.
"Did not provide LastName"
"Did not provide FirstName"
"Did not provide SSN"
instead of "one at a time". (doing it "one at a time" would take potentially many-passes to finally figure out the validity of your checks).
Below is some sample code. Let's say someone tried to buy a book with ISBN "ABC123456".
The below is a custom rule that would check to see if that book exists (in your product database for example). I think you can follow along. It would be wired up against the Book(.cs) poco object. (None of the "wire up" is shown). I'm just trying to give you a quick example of how hard (or not hard) it is to create a simple rule.
When a book is not found (using the isbn)....then you see the validationResults.AddResult method. That is how you get multiple invalids. You'll have access to the collection later when you're checking the validation query.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
namespace MyCompany.Applications.MyApplication.BusinessLogic.Validation.MyType1Validations
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class BookExistsValidatorAttribute : ValidatorAttribute
{
protected override Validator DoCreateValidator(Type targetType)
{
return new BookExistsValidator("BookExistsValidatorTag");
}
}
public class BookExistsValidator : Validator<string>
{
public BookExistsValidator(string tag) : base("BookExistsValidatorMessageTemplate", tag) { }
protected override string DefaultMessageTemplate
{
get { throw new NotImplementedException(); }
}
protected override void DoValidate(string objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
bool bookExists = BookMatchExists(objectToValidate);
if (!bookExists)
{
string msg = string.Format("The Book does not exist. Your ISBN='{0}'", objectToValidate);
validationResults.AddResult(new ValidationResult(msg, currentTarget, key, 10001, this)); /* 10001 is just some number I made up */
}
}
private bool BookMatchExists(string isbn)
{
bool returnValue = false;
IBookCollection coll = MyCompany.Applications.MyApplication.BusinessLogic.CachedControllers.BookController.FindAll(); /* Code not shown, but this would hit the db and return poco objects of books*/
IBook foundBook = (from item in coll where item.ISBN.Equals(book, StringComparison.OrdinalIgnoreCase) select item).SingleOrDefault();
if (null != foundBook)
{
returnValue = true;
}
return returnValue;
}
}
}