A developer’s guide to Page Type Builder

Posted on January 15, 2010 by Frederik Vig in EPiServer

Last updated 19.11.2010

Page Type Builder allows developers to define EPiServer page types in code which eliminates the need to synchronize page types between different servers. As page types are declared in code it also enables inheritance between page types and strongly typed property access.

From the Page Type Builder project

Joel Abrahamsson has done a superb job with the project and is continually working on it. I’ve earlier blogged a little about the project in my Create an EPiServer site from scratch series, but not done a proper walk-through.

New page type

Creating a new page type is very easy. You create a new class, inherit from TypedPageData, and add the [PageType] attribute to the class declaration (living inside the PageTypeBuilder namespace). You have properties for setting the different page type settings.

  • AvailableInEditMode – bool (default true)
  • AvailablePageTypes – Type[]
  • DefaultArchiveToPageID – int (default -1)
  • DefaultChildSortOrder – FilterSortOrder
  • DefaultFrameID – int
  • DefaultPageName – string
  • DefaultSortIndex – int (default -1)
  • DefaultStartPublishOffsetMinutes – int
  • DefaultStopPublishOffsetMinutes – int
  • DefaultVisibleInMenu – bool (default true)
  • Description – string
  • Filename – string
  • Name – string
  • SortOrder – string (default 100)

Example

using PageTypeBuilder;
 
namespace EPiServer.Templates.Public.PageTypes
{
    [PageType(Name = "[Public] Document list", SortOrder = 1140, Filename = "/Templates/Public/Pages/DocumentList.aspx", AvailablePageTypes = new [] { typeof(Document)})]
    public class DocumentList : TypedPageData
    {
    }
}

For a nice overview of how these properties map to the UI in EPiServer admin mode see: How the PageTypeAttribute’s Properties Map to EPiServer CMS’ Admin

Adding properties

You add properties to a page type by adding new public virtual properties to the class with the [PageTypeProperty] attribute. You have properties for setting the various EPiServer property settings.

  • ClearAllLongStringSettings – bool
  • DefaultValue – string
  • DefaultValueType – DefaultValueType
  • DisplayInEditMode – bool (default true)
  • EditCaption – string
  • HelpText – string
  • LongStringSettings – EditorToolOption
  • Required – bool
  • Searchable – bool
  • SortOrder – int
  • Tab – Type
  • Type – Type
  • UniqueValuePerLanguage – bool

Example

[PageTypeProperty(
    EditCaption = "Secondary body",
    HelpText = "The contents of this property will be shown in the right column of the page, you can use both text and images for layout. Note that images should not be larger than the right area.",
    Searchable = true,
    UniqueValuePerLanguage = true,
    Type = typeof(PropertyXhtmlString),
    LongStringSettings = (
	EditorToolOption.All ^
	EditorToolOption.Font),
    Tab = typeof(Advanced))]
public virtual string SecondaryBody
{
    get;
    set;
}

This will add a new property named SecondaryBody of type PropertyXhtmlString (XHTML string (>255)), with all editor options available, except for font. Use ^ for not available, or just add all the options you like with | between.

LongStringSettings = (EditorToolOption.DynamicContent | EditorToolOption.ToggleHtml)

Only DynamicContent and ToggleHtml will now be available for editors.

UniqueValuePerLanguage = false

When setting UniqueValuePerLanguage to false, and using the auto get setter property (like above), you’ll get null values returned on properties in other languages than the master language. To fix this you can use the GetPropertyValue extension method.

[PageTypeProperty(UniqueValuePerLanguage = false)]
public string MyProperty
{
    get 
    { 
        return this.GetPropertyValue(page => page.MyProperty, true) 
    }
}

You should now get the proper value in all languages, not just in the master language.

Tabs

To create a new tab, create a new class and inherit from Tab (PageTypeBuilder.Tab). You now need to implement three abstract properties

  • Name – string
  • RequiredAccess – AccessLevel
  • SortIndex – int

Example

using EPiServer.Security;
using PageTypeBuilder;
 
namespace EPiServer.Templates.Public.Tabs
{
    public class Advanced : Tab
    {
        public override string Name
        {
            get { return "Advanced"; }
        }
 
        public override AccessLevel RequiredAccess
        {
            get { return AccessLevel.Edit; }
        }
 
        public override int SortIndex
        {
            get { return 20; }
        }
    }
}

You can now add properties to this tab by setting the PageTypeProperty’s Tab property.

[PageTypeProperty(Tab = typeof(Advanced))]
public virtual string MyProperty
{
    get; set;
}

Dynamic properties

At the moment you cannot create dynamic properties with Page TypeBuilder. You can however access them.

public virtual string MetaDescription
{
    get
    {
	return this.GetPropertyValue(page => page.MetaDescription, true);
    }
}

As you’ll see when going through EPiServer public templates with Page Type Builder code, I’ve added the dynamic properties to a base class that the other page types inherit from. That way all page types have access to the dynamic properties.

Also be sure to read: Working with Dynamic Properties and Page Type Builder.

Accessing properties in templates

One of the great things about the Page Type Builder is that you not get strongly typed access to your properties.

Web forms (.aspx)

Inherit from the generic TemplatePage (living inside the PageTypeBuilder.UI namespace), where the type is set to the page type this template is for.

using PageTypeBuilder.UI;
 
namespace EPiServer.Templates.Public.Pages
{
    public partial class Document : TemplatePage<PageTypes.Document>
    {
    }
}

When typing CurrentPage. you’ll get access to all the public properties that Document exposes. CurrentPage.SecondaryBody for instance.

User controls (.ascx)

Inherit from the generic UserControlBase (living inside the PageTypeBuilder.UI namespace), where the type is set to the page type this user control is for. If the user control is used by multiple page types, simply find a common class to set as the type (a base class).

using PageTypeBuilder.UI;
 
namespace EPiServer.Templates.Public.Units.Placeable
{
    public partial class Document : UserControlBase<PageTypes.BasePageData>
    {
    }
}

Same as with web forms, you’ll get access the the properties that BasePageData exposes.

EPiServer public templates with Page Type Builder

I’ve started updating the EPiServer public templates to use Page Type Builder. This is not a complete conversion, but merely a nice starting place for you to see how I’ve structured my files and how the code looks when used with an existing project.

Download the code

Other resources

Related Posts: