HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Page types and templates

Explains the concept of pages, page types and templates, and how these are associated in Optimizely Content Management System (CMS). It also describes how to create a simple page type with rendering.



The examples here are based on MVC.

Pages, page types and page templates are linked together in the following way:

  • page type defines a set of properties, for example, page name and publish date.
  • page is an instance of the .NET class defining the page type. When a page is created in edit view, values are assigned to the properties, and stored in the database.
  • The controller and view fetches the stored property values and renders the output.
  • template can be associated with the page type, to render the output in a certain context.

In the following you find examples of how to work with page types and associated controllers, views and templates for rendering the content.



Standard routing is not registered by default for MVC, but if it is used, renaming of a controller or action will affect the URL/route to the action.

Page types

In Optimizely Content Management System (CMS), page types are usually defined in code as classes based on a model inheriting from EPiServer.Core.PageData. A PageData object is the programmatic representation of a page, containing the properties defined in your .NET class. The value of currentPage is automatically set to the PageData object that is requested by the client. During initialization, the bin folder is scanned for .NET classes inheriting PageData. For each of the classes found a page type is created. For all public properties on the class, a corresponding property on the page type is created.

Create a page type

Using the Visual Studio integration, you create a page type by adding the Episerver Page type item to the Pages subfolder under Models in your project. See Getting started with Content Cloud (CMS 11).

To be able to add properties that we want to have for all page types, we added an abstract SitePageData base class, which inherits from EPiServer.Core.PageData. This base class has an SEO property which we want to be used on all pages inheriting from the class.

Example: A simple article page type with a "MainBody" editor area of the property type XhtmlString, inheriting from the SitePageData base class.

using System;
    using System.ComponentModel.DataAnnotations;
    using EPiServer.Core;
    using EPiServer.DataAbstraction;
    using EPiServer.DataAnnotations;
    using EPiServer.SpecializedProperties;
    namespace MyEpiserverSite.Models.Pages
      [ContentType(DisplayName = "ArticlePage", GUID = "b8fe8485-587d-4880-b485-a52430ea55de", Description = "Basic page type for creating articles.")]
      public class ArticlePage : SitePageData
                  Name = "Main body",
                  Description = "The main body editor area lets you insert text and images into a page.",
                  GroupName = SystemTabNames.Content,
                  Order = 10)]
        public virtual XhtmlString MainBody { get; set; }

**Example:** The SitePage base class, with the SEO property.

    namespace MyEpiserverSite.Models.Pages
      public abstract class SitePageData : EPiServer.Core.PageData
        [Display(GroupName = "SEO", Order = 200, Name = "Search keywords")]
        public virtual String MetaKeywords { get; set; }

When creating a page type using the Episerver Visual Studio extension, a unique GUID for the page type is automatically generated. Also, note that page types implicitly contain a set of built-in properties which are available for all pages, regardless of the page type instance. See PageData.Property for built-in properties. 

Since the rendering has not yet been created, pages based on this page type cannot be edited from the On-Page edit view, only from the All Properties edit view.



Why are the properties declared as virtual here? What happens in the background is that a proxy class is created for the page type, and data is loaded from the database to a property carrier (Property), receiving the data. Through Castle (Inversion of Control tool), the properties in the proxy page type will be set, and this only works if properties are declared as virtual. If the properties are not declared virtual, you need to implement get/set so that these will read/write data to the underlying property collection instead.

Page controllers and views

Models, controllers, and views in MVC provide a clear separation of data, business logic, and presentation. The controller contains the business logic, handles URL requests and selects the view, which is a visual presentation of the data model. In MVC, the controller is the class that is registered to support specific page types, and can be regarded as the template. The template defines which content types it can render in a specific context.

Create a controller and a view

Using the Optimizely Visual Studio extension, you create a controller by adding a new CMS item of type Page Controller (MVC) to the Controllers folder in your project. Your controller should inherit from EPiServer.Web.Mvc.PageController<T>, where T is your page type. This controller is called for the page type, if it is chosen as the renderer for the page type. 

To add the corresponding view for the controller, create a subfolder under Views and add an CMS item of type Page View (MVC). Or, click inside the controller to add the view. Ensure that you follow the standard naming conventions in MVC for your model, controllers, and views.

To allow for reuse of logic that we want multiple pages to use, we have implemented a page controller base class, which in this case holds logic for a logout action, and inherits from PageController. You can also add a view model, to be able to add more than just page objects to the views. For simpler examples, we have not used a view model here.

To render properties you can use HTML helpers in MVC, for example Html.PropertyFor, which renders property values based on their property type. HTML helpers are described more below.

Example: The controller for displaying the Article page type, inheriting from PageControllerBase.

using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using EPiServer;
    using EPiServer.Core;
    using EPiServer.Framework.DataAnnotations;
    using EPiServer.Web.Mvc;
    using MyEpiserverSite.Models.Pages;
    using System.Web.Security;
    namespace MyEpiserverSite.Controllers
      [TemplateDescriptor(Default = true)]
      public class ArticlePageController : PageControllerBase<ArticlePage>
        public ActionResult Index(ArticlePage currentPage)
              // Implementation of action view the page. 
              return View(currentPage);

Example: The page controller base, inheriting from PageController, and with SitePageData as generic type.

namespace MyEpiserverSite.Controllers
      public abstract class PageControllerBase<T> : PageController<T> where T : SitePageData
        // Providing a logout action for the page.
        public ActionResult Logout()
            return RedirectToAction("Index");

Example: The corresponding rendering view for displaying the Article page.

@using EPiServer.Core
    @using EPiServer.Web.Mvc.Html
    @model MyEpiserverSite.Models.Pages.ArticlePage
        @Html.DisplayFor(m => m.Heading)
        @Html.PropertyFor(m => m.Introduction)
        @Html.PropertyFor(m => m.MainBody)

With the added rendering using Html.PropertyFor, the property is now also editable in the On-Page editing view.

Use HTML Helpers

You can also use other specific CMS HTML helpers as an alternative to Html.PropertyFor. There are helpers for rendering links, content areas, translations, and navigation. These HTML helpers are called through Html.DisplayFor, but you can also use them directly.

Use templates

Templates define how content is rendered. The template (controller) selected to render a content instance, depends on the specific context. Use the TemplateDescriptor attribute to add metadata and define default templates, and Tags to define which template to use. Based on this information, and any defined display channels and display options settings, the TemplateResolver decides which template to use in a specific context.

Template registration and routing

Page types and controllers created from code using the CMS Visual Studio integration, are strongly typed and inherit from CMS base classes. This ensures that the templates used are automatically registered as supported for the specified page type. See Rendering for more information.