In this tutorial, you will learn about Episerver page-types and how to build them in code. Page types are the most fundamental building block on an Episerver project. All websites are comprised of different types of pages linked together, d'uh! Typically, you would expect to see a homepage, a contact us page, a blog post page etc... A page type is a mechanism to build all of them 🔥🔥🔥

PageData object

Every Episerver page type will need to inherit from the PageData object. The page data object represents and stores all the content and meta data about a specific page. The PageData class is located in the EPiServer.Core namespace. The PageData class contains lot of properties and methods. You do not need to worry about understanding what they all do however, most of them are pretty intuitive. As a developer, the properties that you will likely be using the most include the page Name, the page ID (for finding the page) and LinkUrl (to link to the page).

PageTypes And ContentTypes

Each page type you create will represent a specific type of page on your site. All sites will need a homepage page type, so will use this as an example. Your homepage will be comprised of a number of components. For example, your homepage might include a carousel at the top, a call to action, a newsletter sign-up block, a banner and some text at the bottom. In order to add these components onto a page, you need to add additional properties to your page type. There are a number of different types of Episerver specific properties, you can add to your page type which we will cover in this tutorial. So we know we can create page types in code and we can add properties onto that class in order to create useful templates inside the CMS that content editors can use, great. How do we build one?

Building A PageType

First, let us look at how to create a page-type in code:

The code snippet above shows you everything you need to get started creating your own page-types. All you need to do is decorate a class with the ContentType attribute and inherit from PageData and your page will show up within the CMS. If you taker a closer look at the code, you can see a page-type can be customised quite extensively.

You might be wondering how this works? On application start, Episerver uses reflection to scan all the assemblies in the projects bin folder. If this search finds any classes that have been decorated with the ContentType attribute, it will create a corresponding page-type/template in the Episerver database. The scan also uses reflection to scan all of the properties defined in the class. These are then also created in the Episerver database.

In theory, when a content editor creates a new page in the CMS they are instantiating a new instance of the page-type class, simples 🧐


Before Episerver 7, all an Episerver developer had to learn was the concept of a page, however, from Episerver 7 onwards, the CMS now supports a wider range of content. We now have the concept of IContent.

Content can be used to represent anything you want. You could represent an image, a video, or even a blog post. To make something to be recognised by Episerver as a content type, it has to implement the IContent interface. For example, the Episerver PageData class implements IContent. Found in the EPiServer.Core namespace. The 'IContent' interface at the time of writing, has the following members that you will need to implement 'Name', 'ContentLink', 'ParentLink', 'IsDeleted', 'ContentTypeID', and 'ContentGuid'.

What this means is that you can create any abstraction you need, as long as it inherits from IContent it can be made to play nicely with Episerver. The benefits of implementing something as IContent means that you can use the Episerver IContentRepository helper to access it. On most projects I have worked on, I've never really needed to create my own IContent items, however, if you have a need to do this, I recommend you research Episerer content providers.

Configuring The ContentType Attribute

To define an Episerver page you need to decorate it with the ContentType attribute. ContentType is located in the EPiServer.DataAnnotations namespace and contains these available properties:


Defines if the page will be available in the editor for content editors to use. By default, this is always set to true and you will only need to use unless you want to prevent users from editing that property in the editor.


This will define the blurb that will be rendered next to the property in the editor.


The name that will get displayed in the CMS for the page type.


The position where the object will be displayed in the new page dialogue in the editor. My tip is to always increment this number using a large range, like 100's. The reason for this is to allow you to easily add a new property at a later date. If you only increment the order by 1, you will have to re-numbering everything on the page to add it as you need.


A unique identifier for the page. This is used to ensure your page type is unique. I always recommend you use this. If you don't have a GUID and you do a lot of data migration from older versions, this can potenially acuse import errors. If you want a quick way to generate a new page-type ID you can use this tool, Guid Generator.


The name of the section the item will be grouped in the add new dialogue in the editor

Defining Where Your Pages Can Be Built

In most projects, you will want to restrict what pages can be created under each other, for example a blog page should only be available under a blog home page. To do this you can use the AvailableContentType attribute. This attribute contains these properties:


Defines if all or none content types should be available. If none is set, all other settings on the attribute are ignored.


Specifies which page types can be created underneath it. My recommendation is to just use this approach for defining your rules. I personally find this approach the easiest to implement and it's the one I use in my projects. In this approach, you define a list of everything you want the content editors to create underneath it in the editor.


Specifies the content types that are explicitly not allowed to be created underneath it. I tend to not use this approach as I find it leads to more copying and pasting when setting things up.


This approach allows you to define all the rules on how other pages can interact with it. Instead of using Include which defines a list of items that are allowed underneath it, IncludeOn allows you to define all of the rules self-contained from within the class.


The inverse of above.

Thumbnail Images

In the editor, when a content editor is picking which item to use there's a little thumbnail/preview image that gets rendered with the page type. Unless you add your own custom thumbnail image for your page, this image will be greyed out/missing in the editor. Adding an image can be done by adding the ImageUrl attribute, like this:

Adding an image is simple, however, what do you add? Adding a screenshot of your component being rendered a page can look a bit naff as the image is so small and pixelated. If you are stuck for ideas to use for your page type preview images, then I'd recommend using: to render a banner with a clear name. I tend to use the following configuration:

File Format: PNG Background Color: #7975BA Text Size: 45 Image Height: 300 (uncheck auto) Image Width: 300 (uncheck auto) Alignment: Centered

That covers pretty much everything you need to create Episerver page types. Now go out and create cool things. Happy Coding 🤘