In this tutorial, you will learn how to apply a custom validator to a content area within an Episerver CMS powered website. Before handing over your new build to a content editor, you may want to restrict what blocks an editor can add to a page within the editor. As every project is different, it is likely you will want to apply some bespoke restrictions to the page based on the business needs. For example, you may only want to allow 5 carousel item blocks into a carousel 🚫🚫🚫
In Episerver, there is no easy way to apply these types of restrictions from within the UI itself. It would be possible to create a custom editor rendering for the property. This would involve writing some HTML and JS using Dojo.js. Writing custom editor renderings is painful to debug, it also involves understanding Dojo. Instead, you can create a custom validation attribute using C# alone. This approach is much quicker to build and easier to debug, and it is the approach I recommend you follow.
To create an attribute, you will need to create a class that implements from ValidationAttribute
. Next, override a method called IsValid()
and then create some custom logic. If the validation fails, you return false
from IsValid()
. Doing this will tell the CMS to not save the page. Instead, an error message can be displayed back to the user. Finally, you simply decorate your attribute onto the property you want to add the restrictions to. Simples 🔥🔥🔥
The code to create this attribute can be seen below:
As shown above, the class inherits from ValidationAttribute
and overrides two IsValid()
methods. On Line20, I check the passed-in property type to ensure it is of type ContentArea
, if it is, then the code checks that the Items
collection is not greater than 5.
To apply this attribute to a content area is simple:
Simply decorate the MaxItemsAllowed
attribute within the page or block type property you want to restrict. For most use cases this is the approach I would recommend that you use. There is an alternative way of doing this, which I will cover next.
Validating using IValidate
As of Episerver 7, there is also another way to validate a content area. This approach uses the IValidate
interface. On application start, using reflection Episerver will scan the solutions bin folder for any classes that implements EPiServer.Validation.IValidate
. If it finds any, Episerver will automatically register this validation on a global basis. Whenever a page is saved, Episerver will run all registered global validators any time a page is saved. This approach using reflection works in a similar way as the Episerver code-first content modelling. Registering a new page or block is done in code by decorating a class with the ContentType
attribute. This is all that you need to do in order to register the new type on the CMS. Using reflection on start-up, Episerver will do the rest!
Using the IValidate
method will mean that your validation will be called any time a content editor tries to save a page or block. I am not too keen on this approach for two reasons. First, adding too many validators can make debugging a problem. If you have lots, how do you easily tell which validator has prevented the page from saving? The second is around god classes and code smells. If you mix too many validation rules within a single validator, it is likely you will create bugs and maintenance issues for yourself later on.
To build a validator is simple enough. In your validate method, you simply specify the page type you want to filter by and then put your custom code, like this:
This is all you need to do, as the validator runs globally 🔥🔥🔥
As mentioned, I prefer the attribute approach to validation. I find being specific on validation tends to be easier. I recommend you do whatever makes you happy. Happy Coding 🤘