I've made a validation library which is focusing on model validation. Why another one when there are a few good ones like EntLib Validation ApplicationBlock and Data Annotations?
There are three reasons...
1. It's Extendable
You can easily extend the library in different ways.
Own Validation Rules
You can create your own rules in the following way:
public class CoolnessRule : IRule
{
public string Format(string fieldName, IModelLanguage rulesLanguage)
{
return string.Format(rulesLanguage["Coolness"], fieldName);
}
public bool SupportsType(Type type)
{
return type == typeof (string);
}
public bool Validate(object value)
{
return value.ToString() == "Jonas";
}
}
The Format
method is used when formatting and localizing error messages. Each rule can be more or less complex and might add range restrictions, etc. Therefore, it’s up to the rule to pull the language prompt (in this case “‘{0}’ must be called ‘Jonas’ to be cool“) and add the correct number for parameters.
The SupportsType
method is used to determine if the specified type can be validated by the rule. For instance, the Max rule can validate all primitive types and strings (string
length).
Validate method does the actual validation.
Validate in Different Ways
The actual validation can be done in different ways. Fluent and attribute validations are built in, more about them later. To add your own validation provider, do something like this:
class MyRuleProvider : IRulesProvider
{
public bool Contains(Type type)
{
return type == typeof (Model2);
}
public ModelValidator Create(Type type)
{
ModelValidator validator = new ModelValidator();
validator.Add("FirstName", new RequiredRule());
validator.Add("Department", new BetweenRule(5, 20));
validator.Add("Age", new BetweenRule(18, 65));
return validator;
}
}
The Contains
method determines if this provider has support for the specified type. And the Create
method is used to create the ModelValidator
class containing all the rules.
Then, you just need to add your provider to the library:
Validator.Add(new MyRuleProvider());
2. It’s Multilingual
The multilingual support is quite flexible too. You can easily load language from any source you want. I myself am using text files to be able to categorize entries and use one file per model (I use the translation files for other stuff too, for instance localized error messages).
To load strings from a StringTable
, you can do something like this:
public class LanguageProvider : ILanguagePrompts
{
public string this[string modelName, string promptName]
{
get { return Get(modelName, promptName) ?? "[" + promptName + "]"; }
}
public string Get(string modelName, string promptName)
{
return Resource1.ResourceManager.GetString(modelName + "_" + promptName);
}
}
And to use your provider:
Validator.LanguageHandler = new LanguageProvider();
In your string
table, you create entries like the following ones:
User_FirstName FirstName
User_LastName LastName
i.e. ModelName
underscore PropertyName
.
3. It’s Flexible
The library doesn’t force you to use validations in a certain way. You can use your own favorite way of creating validations.
The two built in providers use either code or attributes to provide validations.
Attribute Validation
public class MyModel
{
[Required]
public string FirstName {get;set;}
[Required, Min(15)]
public string LastName {get;set;}
}
FirstName
is required and LastName
is required and must be maximum 15 characters long.
Your own validation rules will automatically be added to the validator when using attribute validation.
Fluent Validation
Fluent validation means that you create a class which is used to validate models. The class is automatically loaded and instantiated by the library, all you need to do is to create it and place it in the same namespace as the model. It should be named [YourModelName]Validator
, i.e. UserValidator
.
public class MyModelValidator : FluentValidator<MyModel>
{
public MyModelValidator()
{
Property("FirstName").Required();
Property("LastName").Required().Min(15);
}
}
To add support for your own validation rules, simply create extension methods for the Property
class:
public static Property Tired(this Property instance)
{
instance.Add(new TiredRule());
return instance;
}
Usage
The most important part is how the library is used, right?
User user = new User();
user.FirstName = "Jonas";
var errors = Validator.Validate(user);
if (errors.Count > 0)
{
}
Source Code
The source code can be found at CodePlex.
Share and Enjoy: