A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Alexander Haneng
Jan 16, 2013
  13096
(6 votes)

Limiting a Page Property to a specific Page Type in EPiServer 7

In EPiServer 7 you can limit what page types can be selected in a page or link collection property using validation attributes.

 

Intro

One of the big problems with EPiServer sites that have lived a while is when some clever editor decides to change a page property. It just so happens that this specific page property is used to get a page of a specific page type that contains some important properties that are used for settings/header/footer/search page etc. For example a page property on the start page that links to a settings page gets changed to an article page. This might result in the whole site crashing. Arghhh…

 

Limiting page types for a page property

In EPiServer 7 we get to create our own validation attributes, so why not create a validation attribute that prevents the user from selecting the wrong page type?

I have created such an validation attribute. Simply add this class to your project and you can start using it. You can find the source code at the end of this article

 

Using the [LimitPageType] attribute to limit a page property to a specific page type

Lets say we have a settings page in our solution and we have a page property that points to the search page for our site. We want to ensure that only a page of the page type “SearchPage” can be selected.

 

[LimitPageType(typeof(SearchPage),
    ErrorMessage = "Page '{2}' is not of page type '{1}'! " +
                   "(It is of the type '{3}')")]
[Display(
Name = "Search page",
Description = "",
GroupName = SystemTabNames.Content,
Order = 1)]
public virtual PageReference SearchPage { get; set; }

 

If we try to select the page “Management” of type “StandardPage” we will get the following error:

image

 

Using inheritance

You can also use inheritance, so if you limit the page property to “StandardPage” you can select a page of the type of “StandardPage” or any page inherited from “StandardPage” like “NewsPage” and “ProductPage”.

 

[LimitPageType(typeof(StandardPage),
    ErrorMessage = "Page '{2}' is not of page type '{1}'! " +
                   "(It is of the type '{3}')")]
[Display(
Name = "About us page",
Description = "",
GroupName = SystemTabNames.Content,
Order = 2)]
public virtual PageReference AboutUsPage { get; set; }

 

Using the [LimitPageType] attribute to limit a page property to an interface

You are not limited to page types, you can also specify an interface to only allow page types that implements a specific interface to be selectable. This ensures that the properties defined in the interface will be included in the selected page.

 

[LimitPageType(typeof(ISearchable),
    ErrorMessage = "Page '{2}' is not of type '{1}'!")]
[Display(
Name = "Searchable page page",
Description = "",
GroupName = SystemTabNames.Content,
Order = 3)]
public virtual PageReference SearchablePage { get; set; }

 

 

Using the [LimitPageType] attribute to limit a Link Item Collection property to only contain pages of a specific page type

The validation attribute also works on the LinkItemCollection property and it checks that all the items are EPiServer pages of the correct page type. In this example we only want to have a list of contact pages of the type “Contactpage”.

 

[LimitPageType(typeof(ContactPage),
    ErrorMessage = "Link '{2}' is not a page of type '{1}'!")]
[Display(
Name = "Contacts",
Description = "",
GroupName = SystemTabNames.Content,
Order = 4)]
public virtual LinkItemCollection Contacts { get; set; }

 

 

image

 

image

 

Summing up

The built in validation attributes like StringLength, Range and RegularExpression are really powerful in validating the input from editors, especially when you need to use it for something more than just displaying the value. This power can be further extended with custom validation attributes like the one in this blog post. I am sure more validators will be released by the community as EPiServer 7 matures.

 

Source code: LimitPageType.cs

For the examples in the blog post to work you need to create an empty class in your project and copy and paste the code below inside.

 

using System;
using System.Collections.Generic;
using System.Globalization;
using System.ComponentModel.DataAnnotations;
using EPiServer.Core;
using EPiServer.SpecializedProperties;
using EPiServer.Web;
 
namespace EPiServer.Templates.Alloy.Validation
{
    /// <summary>
    /// LimitPageType Validation Attribute
    /// Add the attribute [LimitPageType(typeof(StandardPage))] to a EPiServer 
    /// PageReference property to limit what pages can be selected to the 
    /// chosen page type. Can also be used for inherited page types and 
    /// interfaces.
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, 
        AllowMultiple = false)]
    public sealed class LimitPageType : ValidationAttribute
    {
        private readonly Type _pageType;
        private string _errorMsg = string.Empty;
 
        public Type PageType { get { return _pageType; } }
 
        public LimitPageType(Type PageType)
        {
            _pageType = PageType;
        }
 
        public override bool IsValid(object value)
        {
            // Check if page reference is a reference to a page of 
            // the right page type
            PageReference pageRef = value as PageReference;
            if (pageRef != null)
            {
                PageData page = DataFactory.Instance.GetPage(pageRef);
 
                _errorMsg = page.PageTypeName;
 
                if (!this.PageType.IsInstanceOfType(page))
                    return false;
            }
            else if (value as LinkItemCollection != null)
            {
                //Loop through and check if it is a link to an EPiServer page. 
                //If it is add it to pages.
                LinkItemCollection linkItems = value as LinkItemCollection;
                List<PageData> pages = new List<PageData>();
                foreach (LinkItem linkItem in linkItems)
                {
                    string linkUrl;
 
                    if (!PermanentLinkMapStore.TryToMapped(linkItem.Href, 
                        out linkUrl))
                    {
                        _errorMsg = linkItem.Text;
                        return false;
                    }
 
 
                    if (string.IsNullOrEmpty(linkUrl))
                    {
                        _errorMsg = linkItem.Text;
                        return false;
                    }
 
                    PageReference pageReference = PageReference.ParseUrl(linkUrl);
 
                    if (PageReference.IsNullOrEmpty(pageReference))
                    {
                        _errorMsg = linkItem.Text;
                        return false;
                    }
 
                    pages.Add(DataFactory.Instance.GetPage((pageReference)));
                }
 
                if (pages.Count > 0)
                {
                    foreach (PageData page in pages)
                    {
                        if (!this.PageType.IsInstanceOfType(page))
                        {
                            _errorMsg = page.PageName;
                            return false;
                        }
 
                    }
                }
 
                return true;
            }
 
            return true;
        }
 
        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentCulture,
              ErrorMessageString, name, this.PageType.Name, _errorMsg);
        }
    }
}
Jan 16, 2013

Comments

Jan 16, 2013 02:13 PM

Very useful. I'm pretty sure I'll be using this in every EPi7 project.

Jan 17, 2013 10:41 AM

Limiting a multipage property to a certain set of allowed page types has of course been available in MultiPagePropertyPlus for years ;)

https://www.coderesort.com/p/epicode/wiki/MultiPagePropertyPlus

Just check out the AllowedPageTypes attribute:

https://www.coderesort.com/p/epicode/attachment/wiki/MultiPagePropertyPlus/ScreenshotUsage.jpg

Joshua Folkerts
Joshua Folkerts Jan 21, 2013 06:41 AM

This is great Alexander. I have needed this for quite some time. Thanks for sharing this.

Jan 21, 2013 03:28 PM

I actually wrote this back in July 2012 and pitched EPiServer to make it a standard part of CMS 7, but it is pretty easy to add the single class to your project.

raymond
raymond Feb 14, 2013 01:40 PM

Can you get a warning instead of an error?
I want the user to get a warning when publish but not an error and the page should be published.

Please login to comment.
Latest blogs
Looking back at Optimizely in 2025

Explore Optimizely's architectural shift in 2025, which removed coordination cost through a unified execution loop. Learn how agentic Opal AI and...

Andy Blyth | Dec 17, 2025 |

Cleaning Up Content Graph Webhooks in PaaS CMS: Scheduled Job

The Problem Bit of a niche issue, but we are building a headless solution where the presentation layer is hosted on Netlify, when in a regular...

Minesh Shah (Netcel) | Dec 17, 2025

A day in the life of an Optimizely OMVP - OptiGraphExtensions v2.0: Enhanced Search Control with Language Support and Synonym Slots

Supercharge your Optimizely Graph search experience with powerful new features for multilingual sites and fine-grained search tuning. As search...

Graham Carr | Dec 16, 2025

A day in the life of an Optimizely OMVP - Optimizely Opal: Specialized Agents, Workflows, and Tools Explained

The AI landscape in digital experience platforms has shifted dramatically. At Opticon 2025, Optimizely unveiled the next evolution of Optimizely Op...

Graham Carr | Dec 16, 2025

Optimizely CMS - Learning by Doing: EP09 - Create Hero, Breadcrumb's and Integrate SEO : Demo

  Episode 9  is Live!! The latest installment of my  Learning by Doing: Build Series  on  Optimizely Episode 9 CMS 12  is now available on YouTube!...

Ratish | Dec 15, 2025 |

Building simple Opal tools for product search and content creation

Optimizely Opal tools make it easy for AI agents to call your APIs – in this post we’ll build a small ASP.NET host that exposes two of them: one fo...

Pär Wissmark | Dec 13, 2025 |