EPiServer  /  CMS July 12, 2010

Help your editors with a smarter PageReference property

Two key factors for building a successful site based on EPiServer CMS is that it’s easy and intuitive for editors to publish content and that the site is built in a way so that it’s easy to maintain. One way of helping, or rather guiding, the editors that I’ve been wanting to do for quite some time would be to create a custom property with which an editor only can select pages that are of a specific, or a group of specific, page types.

EPiServer CMS's Page Browser dialog When I’ve been thinking about how to build such a property I’ve usually ended up thinking about how the editor should do the actual selecting of a page. That is, what I should replace the standard Page Browser dialog (shown in the image to the right) with that would only show pages of page types that the editor can select.

Replacing the standard Page Browser dialog comes with problems. First of all it would introduce a new, none-standard, way of selecting pages that isn’t covered in the editors manual and standard editor training. Therefore, while the GUI might be intuitive it might be counterproductive. Perhaps even worse though is that it would be complicated from a technical perspective, requiring me to build a new dialog, perhaps not only with server side code but also with some client side code that should work in most browsers and be able to stand the test of time with new versions of the CMS, new browsers etc.

Remember that I said that I think maintainability is a key factor for building a successful site? Well key to maintainability in turn is often simplicity and a custom dialog wouldn’t be a simple solution.

So what would be?

What we’re really after here is helping the editor make the right decision. And while it would be nice to ensure that he or she could only see pages that are valid for selection it would be quite sufficient to just validate that whatever page the editor has selected is of the correct type when the editor tries to save the page. Doing that would be a very simple and future-safe solution that would more or less just reuse built-in functionality in EPiServer CMS.

The TypedPageReference project

To accomplish this I created a small, new project named TypedPageReference. The source code is available on GitHub and you can download a ready to use, compiled, version here.

At the time of this writing the project comes with two base classes for custom properties, PropertyTypedPageReference and PropertyQuickEditPageReference. I won’t go into any details of how they are implemented (they are both very simple) but you are very welcome to browse or download the source code on GitHub.

Note that in order to use this project you need to be using Page Type Builder on your site.

Using PropertyTypedPageReference

In order to create a custom property that restricts what page types that the editor can select you create a new custom property that inherits from PropertyTypedPageReference<T>. For instance, let’s say that you have a site that have the same page types as the public templates (you can easily create such as site using Erik Nordin’s excellent tool). In that all page types except the one named “[Public] RSS source” has a MainBody property. We can formalize this by creating an interface named IHaveMainBody that we let the other page type classes implement. The interface looks like this:

public interface IHaveMainBody
    string MainBody { get; }

Next let’s say that we would like to add a new property to the start page with which the editor can select a page from which we fetch the MainBody property. Now if the editor were to select a page of the RSS Source page type our code that uses the MainBody property would either crash and burn as the referenced page doesn’t have a MainBody property or, in the case that we handle that scenario, nothing would happen and the editor would wonder why nothing has changed although she has modified the start page to fetch the text from a page.

To handle that you can create a custom PageReference property that will only allow the editor to select pages who’s page types implement the IHaveMainBody interface. Doing so is very easy, just create a new property that inherits from PropertyTypedPageReference<IHaveMainBody>.

using System;
using EPiServer.PageTypes;
using EPiServer.PlugIn;
using TypedPageReference;

public class PropertyMainBodyPageReference 
    : PropertyTypedPageReference<IHaveMainBody>

And make sure that your property is of that type.

using System;
using EPiServer.CustomProperties;
using EPiServer.PageTypes;
using PageTypeBuilder;
using EPiServer.Core;
using PublicTemplates.Tabs;

[PageType(Name = "[Public] Start page",
    Filename = "/default.aspx"]
public class Startpage : TypedPageData, IHaveMainBody
    [PageTypeProperty(Type = 
    public virtual PageReference MainBodyPage { get; set; }

Now, if the editor selects a page who’s page type doesn’t implement IHaveMainBody she’ll get a validation error when she tries to save the page.

Validation error message in EPiServer CMS's edit mode when saving a page

As you can see the error message is quite detailed telling the editor not only that she’s selected a page of the wrong type but also what page types are valid to select. Of course in a more realistic scenario there would probably be fewer page types that are valid and the error message would be shorter.

Customizing PropertyTypedPageReference

The PropertyTypedPageReference base class is highly extendable and it’s easy to customize your properties that inherit from them. One thing that you can do is for instance to customize the error message by overriding the GetWrongTypeErrorMessageTemplate method.

public class PropertyMainBodyPageReference 
    : PropertyTypedPageReference<IHaveMainBody>
    protected override string GetWrongTypeErrorMessageTemplate()
        return @"You need to select a page that has a Main body. 
        Valid page types are {0}.";

The custom error message displayed in EPiServer CMS's edit mode

You can also override the WrongTypeErrorMessageLanguageKey property to globalize the error message, override the GetValidPageTypes method to change the logic by which valid page types are identified, override the CreateTypedPageReferenceControl method to change what control is added etc. Well soon see an example of the latter when we look at PropertyQuickEditPageReference.

Using PropertyQuickEditPageReference

Another way that we can help editors in their daily work is to make it easier to navigate and work in edit mode. Therefore I created another base class for custom PageReference properties named PropertyQuickEditPageReference which will add a link to the property in edit mode with which the editor can open the referenced page for editing in a popup to be able to quickly look at, or edit, the contents of the referenced page. I think this can come in particularly handy when working with sites where certain pages are actually teasers/widgets that are included on other pages.

PropertyQuickEditPageReference inherits from PropertyTypedPageReference and you use it the same way, by creating a custom property that inherits from it. Let’s change our previous example to use it:

public class PropertyMainBodyPageReference 
    : PropertyQuickEditPageReference<IHaveMainBody>
When we again view the start page in edit mode we can see that the property now has a link below it.

The MainBodyPage property displayed in EPiServer CMS's edit mode with a link named Quick edit below it

Click the link and the referenced page will be opened in quick edit mode in a popup window.

A page displayed in EPiServer CMS's simple edit mode in a popup window

Customizing PropertyQuickEditPageReference

The PropertyQuickEditPageReference is also highly customizable in that you can override pretty much everything. To change the link text you can override the GetQuickEditLinkText method and to globalize it you can override the QuickEditLinkTextLanguageKey property. You can change the width and height of the popup (it defaults to 700*500) by overriding the PopupWidth and PopupHeight properties.

Conclusion and final notes

It’s important to note that while these properties restrict what pages can be referenced in edit mode they are not restricting what pages that they can reference in other scenarios. You can still make an instance of PropertyMainBodyPageReference from our example reference a page of type RSS Source by setting it programmatically or by changing the type of the referenced page in admin mode.

In other words: these properties are intended to help you help the editors, not to provide a bullet proof way of knowing the type of a referenced page.

I’m quite happy with how the PropertyTypedPageReference class works and although there certainly is room for improvements, we could for instance customize the Page Browser it uses a little, I don’t foresee any major changes to it unless someone points out a flaw in it (please leave a comment if you see such a flaw!).

As for the PropertyQuickEditPageReference it’s more of an experiment so far and there are a few things that I would like to try out with it, such as being able to set the popup’s size using property settings in admin mode and opening up the class so that you could provide different strategies for creating the link. I’ll see if I can find the time and energy :)

If you have ideas for improvements or any other types of feedback please leave a comment!

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more


comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer CMS