In previous versions of EPiServer custom validation was normally achieved in one of two ways. You could either create a custom property or hook into a DataFactory event.

Both approaches had their disadvantages and advantages. However in EPiServer 7 a new way of validation has been introduced, namely the EPiServer.Validation.IValidate<T> interface (thanks to Johan Bjornfot for the tip!).

How does it work?

At start up the EPiServer framework scans for any assemblies that implement EPiServer.Validation.IValidate<T> and executes the Validate() method any time a page or block is saved (note this is called during auto-save operations too).

So how do we code this?

The code itself is pretty simple and I hope self explanatory:

public class StandardPageValidator : IValidate
    IEnumerable IValidate.Validate(StandardPage instance)
        // Silly example to validate if the PageName and MainBody properties start with the same letter
        if (instance.PageName.StartsWith(EPiServer.Core.Html.TextIndexer.StripHtml(instance.MainBody.ToHtmlString().Substring(0, 1), int.MaxValue)))
            return new[] { new ValidationError() { 
                ErrorMessage = "Main body and PageName cannot start with the same letter", 
                PropertyName = "PageName", RelatedProperties = new string[] { "MainBody" }, 
                Severity = ValidationErrorSeverity.Error, 
                ValidationType = ValidationErrorType.AttributeMatched
            } };

        return new ValidationError[0];

There are some obvious advantages to this approach:

  • Validation is kept in distinct, clean classes and not mixed with any other custom code.
  • It's type safe (though that is due to the use of typed content!).
  • It can also be applied to page types and block types that implement an interface. This is really nice as your validation code can be reusable.


All in all I really like this approach. It encourages us to keep our validation separate and can be easily be added to an existing EPiServer 7 build without affecting the core page type or block type model.