Validation Application Block (VAB) Windows Workflow Rules Engine Integration - Part 1
Validation Application Block (VAB) Windows Workflow Rules Engine Integration - Part 1
When I first read about the Validation Application Block (in Enterprise Library 3.0) I started thinking about integrating it with the Rules Engine that ships with Windows Workflow Foundation. The first integration point that has crossed my mind was to create a Custom Validator that validates an object according to business rules.
The WF Rules Engine receives an object and executes the rules against it. But, in order to log the validation errors if found, I have to call a method that will collect all the validation results. To solve this issue I created a generic type that will hold both the validated object, but also will contain the LogValidationResult method.
When implementing a Custom Validator, the core logic is found in the DoValidate method:
protected override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
// Get the RuleSet to execute from the Rules Provider
// In the future, a factory will be used to get the rules provider
IRulesProvider rulesProvider = new FileRulesProvider();
RuleSet rs = rulesProvider.GetRuleSet(this.ruleset);
// Create a generic type with type argument as the type of the validated object
Type rulesValidatorResultsType = typeof(RulesValidatorResults<>);
Type genericRulesValidatorResultsType = rulesValidatorResultsType.MakeGenericType(objectToValidate.GetType());
// Call its constructor with the validator, validation results conllection and the object to validate
ConstructorInfo ci = genericRulesValidatorResultsType.GetConstructor(
new Type[] { typeof(Validator), typeof(ValidationResults), objectToValidate.GetType() });
object targetResults = ci.Invoke(new object[] { this, validationResults, objectToValidate });
// Execute the rules
RuleValidation validation = new RuleValidation(genericRulesValidatorResultsType, null);
RuleExecution execution = new RuleExecution(validation, targetResults);
if (rs.Validate(validation))
{
rs.Execute(execution);
}
else
{
throw new Exception(validation.Errors[0].ErrorText);
}
}
Notes and Thoughts:
Validation Application Block supports using its own RuleSets. I would recommend changing this name to another name, since it conflicts with the WF RulesSets.
Future Directions:
- Configuration support for the Rules Validator.
- Configuration support for the Rules Providers.
- Try to avoid the use of RuleValidationResults<T> class.
- Maybe a screencast??
Using the code samples:

After downloading Enterprise Library 3.0, you can download the code samples of this post. The solution contains 5 projects:
- Common and Validation are the referenced Enterprise Library projects that are being used in this sample.
- Bursteg.Validators project contains the RulesValidator and the RulesValidatorAttribute classes. Additionally, this project contains some Rules Providers that can read the rules definitions from file or database. This project also contains the SQL script that is required to create the sample rules database.
- Bursteg.BusinessEntities contains a sample Order entity that uses a RangeValidator and the RulesValidator.
- Bursteg.TestProgram contains a sample console application that validates an Order instance agains a RuleSet.
- Build the sample solution and make sure that the Bursteg.TestProgram project is the startup project. Run the solution.
- The Rule Set Editor Dialog will show. Click the Add Rule button to add new rule. Fill the following fields:
Condition: this.value.Amount > 3.0m
Then Actions: LogValidationResult("Value cannot be above 3!", "Amount")
- Click OK.
- Since the Order instance is not valid you'll get the list of validation errors collected during the validation process. Notice that the Value cannot be above 3! message appears.
- Run the sample again with different validation rules.
I'd love to hear any comments or suggestions you may have.
Enjoy!