Click here to Skip to main content
11,717,126 members (81,786 online)
Click here to Skip to main content

Castle Validator Component for Beginners

, 10 Sep 2011 CPOL 11.2K 237 9
Rate this:
Please Sign up or sign in to vote.
In this article, I will explain how to use Castle validator component in an application and how it works from inside out.

Introduction

Castle validator component is an open source validation framework that uses property attribute to specify validation rules on class. In this article, I will explain how to use it and how it works from inside out.

Castle Validator Sample

Let’s start by looking at a class that has Castle validator attributes on it.

public class User
{
	[ValidateLength(3, 10)]
	public string Name { get; set; }

	[ValidateDate("Invalid date format.")]
	public string DOB { get; set; }
	
	[ValidateEmail("Invalid email address.")]
	[ValidateLength(5, 20, RunWhen = RunWhen.Insert)]
	public string Email { get; set; }
}

There are three validator attributes used here: ValidateLength, ValidateDate, and ValidateEmail.

  • ValidateLength attribute is used to specify a fixed length or length range for the property.
  • ValidateDate attribute is used to specify the property as date type.
  • ValidateEmail attribute is used to specify the property allows email format.

A castle validator attribute inherits from AbstractValidationAttribute that ultimately inherits from Attribute and IValidatorBuilder. The IValidatorBuilder is the contract that Castle validator attribute must implement. By implementing this contract, validate attribute is able to create a corresponding validator for validation process by ValidatorRunner.

ValidateLengthAttributeClass.gif

The following code sample shows how to use ValidatorRunner validates the class that has validator attributes on it.

[TestMethod]
public void CreateUser_User_NoError()
{
	//Assign
	ValidatorRunner runner = new ValidatorRunner(new CachedValidationRegistry());

	User user = new User();
	user.Name = "Henry";
	user.DOB = "1/1/2011";
	user.Email = "henry@aaa.com";

	//Act
	bool result = runner.IsValid(user);

	//Assert
	Assert.IsTrue(result);
	ErrorSummary errorSummary = runner.GetErrorSummary(user);
	Assert.AreEqual(0, errorSummary.ErrorsCount);
}

The ValidatorRunner is the class that has knowledge of how to execute validators. All validators are from CachedValidationRegistry. When runner is calling IsValid method, it will ask CachedValidationRegistry for all validators of the current object. Then use Validation Performer internally to perform validation process on the object. The result is stored in ErrorSummary for later use.

IsValid.gif

Some Good Validation Features

As a useful validation framework, some features are designed for advanced scenarios. I am not going to go through the entire advanced features, just a few of them that I feel make Castle Validator distinguished with other validation framework.

RunWhen

If the validation is only legitimate for certain situations, you can use RunWhen parameter with validator attribute to specify when you want to have this validation. RunWhen is an enum that can be Everytime, Insert, Update, and Custom. The default is Everytime. Following is a Validator attribute that has RunWhen used.

[ValidateLength(5, 20, RunWhen = RunWhen.Insert)]
public string Email { get; set; }

Let’s see how to validate it:

[TestMethod]
public void CreateUser_User_EmailErrorWhenInsert()
{
	//Assign
	ValidatorRunner runner = new ValidatorRunner(new CachedValidationRegistry());

	User user = new User();
	user.Name = "Henry";
	user.DOB = "1/1/2011";
	user.Email = "henry@aaaaaaaaaaaaaaa.com";

	//Act
	bool result = runner.IsValid(user, RunWhen.Insert);

	//Assert
	Assert.IsFalse(result);
	ErrorSummary errorSummary = runner.GetErrorSummary(user);
	Assert.AreEqual(1, errorSummary.ErrorsCount);
	Assert.AreEqual("Field must be between 5 and 20 characters long", 
			errorSummary.ErrorMessages[0]);
}
Execution Order

When there are multiple validator attributes applied on a property, you can use execution order on validator attribute to specify which one executes first.

[ValidateNonEmpty(FriendlyName="Country Field", ExecutionOrder=1)]
[ValidateLength(3, 10, "Invalid country length.", ExecutionOrder=2)]
public string Country { get; set; }
ValidateSelf

If you have a pretty complicated validation logic and don’t want to create a custom validator attribute for it because it’s used once in that particular class only, you can create a method to do validation and use ValidateSelf attribute to let Castle validator component find it.

[ValidateSelf()]
public void Validate(ErrorSummary errorSummary)
{
	if ((Street == null || !Street.Equals
		("Main Street", StringComparison.InvariantCultureIgnoreCase)) && 
		(City != null && City.Equals("Big City")))
		errorSummary.RegisterErrorMessage("Street", 
			"Street name must be Main Street when City is Big City.");

}

Custom Validation

For situations in which you want to have specific business logic validation and also want to apply it to multiple places, custom validation is the best option. To create a custom validation, you need to create a custom validator attribute and custom validator. The validator attribute is used to decorate property and the validator is the one doing validation.

ValidateCityAttribute
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | 
	AttributeTargets.ReturnValue, AllowMultiple = true), CLSCompliant(false)]
[Serializable]
class ValidateCityAttribute : AbstractValidationAttribute
{
	private readonly IValidator _validator;

	public ValidateCityAttribute()
	{
		_validator = new CityValidator();
	}

	public ValidateCityAttribute(string errorMessage)
		: base(errorMessage)
	{
		_validator = new CityValidator();
	}

	public override IValidator Build()
	{
		base.ConfigureValidatorMessage(_validator);
		return _validator;
	}
}
CityValidator
[Serializable]
public class CityValidator : AbstractValidator
{
	public override bool SupportsBrowserValidation
	{
		get
		{
			return false;
		}
	}

	public CityValidator()
	{
	}

	public override bool IsValid(object instance, object fieldValue)
	{
		if (fieldValue == null)
		{
			return true;
		}
		if (fieldValue != "Big City" && fieldValue != "Small City")
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	protected override string BuildErrorMessage()
	{
		return "City must be Big City or Small City.";
	}
}

Let’s also take a look at the class diagram:

CustomValidation.gif

Summary

Castle validator component is a very simple and flexible validation framework. It can be used in all kinds of applications: Web, Windows, Console, etc. Even better, this validation framework allows customization easily and deeply to fit your exact need.

Using the Code

The code is developed in Visual Studio 2010. Castle validator component (Castle.Components.Validator.dll) 4.0.30319 is used with the code.

History

  • 10th September, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Henry He
Software Developer (Senior)
United States United States
Senior Software Developer from New Jersey, USA

Have 15+ years experience on enterprise application development with various technologies.

You may also be interested in...

Comments and Discussions

 
QuestionGood article, BUt I guess most people would just use the standard .NET classes Pin
Sacha Barber16-Sep-11 3:31
mvpSacha Barber16-Sep-11 3:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150901.1 | Last Updated 10 Sep 2011
Article Copyright 2011 by Henry He
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid