Kentico 12: Design Patterns Part 25 - MVC Page Templates
Tags: dotnet, kentico, mvc, cms
Published: 2020-07-01 15:08:15

---
title: Kentico 12: Design Patterns Part 25 - MVC Page Templates
published: true
description: Learn about Kentico 12 MVC Page Templates, what they're for, how they work, and the details behind them.
tags: dotnet, kentico, mvc, cms
series: Kentico 12 - Design Patterns
---

![A blank notepad and watercolor paints and brushes](https://thepracticaldev.s3.amazonaws.com/i/whins3h44uthzltmrxh3.jpg)

I gotta be honest - my first few attempts to understand how Page Templates work in Kentico 12 MVC resulted in utter failure 😖.

They're not quite traditional MVC renderings and they're not fully Page Builder components.

Instead they're a cool and weird hybrid with a multi-step process for handling an HTTP request 😵.

What are MVC Page Templates? What kinds of scenarios are they good for? How do they work behind the scenes? How do I get started with them?

In this post I'll attempt to give helpful answers for all these questions 😂.

---

## What are Kentico 12 MVC Page Templates?

I've found the easiest way to think of Page Templates is this:

> Page Templates let the content managers select an MVC View to render a Page in the content tree.

That's it! End of the blog post!

...

Just kidding 😁.

But really, that's about all there is to it on a conceptual level.

In the screen capture below, I'm creating a new Page that uses MVC Page Templates. When choosing one of the "Default templates", I'm really choosing an MVC View.

![Creating a new page in Kentico using Page Templates](https://dev-to-uploads.s3.amazonaws.com/i/q6k4sweezmoz7g61robk.gif)

MVC Page Templates give developers a way to enable and present dynamic View selection to content managers through a standard pattern with a nice UI.

Of course, MVC Page Templates include lots of other features and functionality 💪🏽, but their main purpose is to provide a predefined set of variations for rendering a Page's content.

---

## When Would We Use MVC Page Templates?

The most obvious use case for MVC Page Templates is to change the layout of a page's content - repositioning that content in different parts of the page [depending on the Template selected](https://docs.kentico.com/k12sp/managing-website-content/using-page-templates-in-mvc#UsingpagetemplatesinMVC-Creatingpagesbasedonpagetemplates).

However we could also use them when we want to completely change the code of the page by building Page Templates that use different MVC `_Layout.cshtml` files, with different CSS, JavaScript, and MVC Partials or Child Actions 🤔.

To add to this scenario, there's a perfectly valid use-case for Page Templates combined with Pages that have little, or no, content themselves. Instead, we rely on Editable Areas to provide content managers with locations in the layout where they can add any number of MVC Widget Sections and Widgets 🤓.

These Editable Areas can then be re-positioned with the different layouts in each Page Template.

---

## What Other Features Do MVC Page Templates Have?

While selecting an MVC View for a given Page is a pretty compelling feature, Page Templates also come with a couple other neat perks 🎉.

### Page Template Properties

Page Templates can have [custom and configurable properties](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-page-templates-in-mvc/defining-page-template-properties-in-mvc), just like [MVC Widgets and Widget Sections](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-widgets-in-mvc/defining-widget-properties-in-mvc).

This means we can customize the look and feel of a page after having selected a specific Page Template for the Page.

In the screen capture below you can see how I use the Page Template properties icon to open the properties dialog and change the "Show Hero" value.

![Toggling a Page Template's property on and off](https://dev-to-uploads.s3.amazonaws.com/i/y8lalucf7n4es47s5ilt.gif)

Generally, enabling content managers to change the structure (layout) of a page should be accomplished by providing multiple MVC Page Templates ✔.

A good example would be whether the sidebar of a page in on the left or right. Or switching between a full page width layout compared to one with a constrained and centered content column.

On the other hand, exposing smaller, non-structural, cosmetic options for a Page can be done through MVC Page Template Properties ✔.

These cosmetic changes might be setting the background color of a Page, or specifying how many images to display in a gallery.

### Page Template Filtering

Page Templates are registered globally in the content delivery (MVC) application. But not all Page Templates are applicable to all Pages on the site 🤨.

We can use [Page Template Filters](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-page-templates-in-mvc/filtering-page-templates-in-mvc) to restrict a Page Template to Pages of a specific type.

These filters work in much the same way as [specifying which MVC Widgets are allowed](https://docs.kentico.com/k12sp/developing-websites/page-builder-development/creating-pages-with-editable-areas-in-mvc#CreatingpageswitheditableareasinMVC-Addingeditableareastoviews) to be used in a given Editable Area 👍🏾.

### Custom Page Templates

MVC Page Templates are MVC Views, and when rendered, work just like for any other normal page 🤗.

This means we can include Editable Areas in them so that content managers can added Widget Sections and Widgets to the Page, which leads to one of the most interesting features of Page Templates...

... the ability to [save the Page Builder configuration](https://docs.kentico.com/k12sp/managing-website-content/using-page-templates-in-mvc#UsingpagetemplatesinMVC-Savingpagesascustompagetemplates), added to a Page Template Page, as a Custom Page Template 😮.

Below you can see how I change the Page Template properties, by hiding the hero image, add a Content Widget, and then save everything as a Custom Page Template named "Landing Page with Content".

![Creating a new Custom Page Template and toggling between the default Templates and the custom one](https://dev-to-uploads.s3.amazonaws.com/i/6ahldblfj92xy4wjfp5z.gif)

Switching back to the 2 Default templates restores the Page to the default state for those templates, but changing to the custom "Landing Page with Content" template loads the Page Template property and Widget state that I previously saved 🤯.

#### How Do Custom Page Templates Work?

The Widget configuration for a given page is stored in the `CMS_Document.DocumentPageBuilderWidgets` column and the configuration for a given page's Page Template is stored in the `CMS_Document.DocumentPageTemplateConfiguration` column.

When creating a Custom Page Template, a new row is created in the `CMS_PageTemplateConfiguration` table and both of the above `CMS_Document` columns for a Page are copied to the `PageTemplateConfigurationWidgets` and `PageTemplateConfigurationTemplate` columns respectively.

Then, when a new Page is created using that Custom Page Template, those `CMS_PageTemplateConfiguration` table column values get copied to the `CMS_Document` columns for the new Page 🧐.

There currently isn't a way to update an existing Custom Page Template 😕, we but we can always create new ones from an existing Page 🤷🏿‍♂️.

When selecting a Custom Page Template while creating a new Page, what we are really doing is selecting a Page Template that we've registered in code, combined with a snapshot of Page Template property values and Widget/Widget Sections with their properties 😮.

We aren't ever storing any reference to the Custom Page Template as part of Page's values - it's just a copy/paste.

This means we're safe to delete any Custom Page Templates without affecting any existing Pages 👍🏽.

> However, removing a Page Template registration from our code for an in-use Page Template _would_ affect our existing Pages - they'd throw and exception and fail to render 😨!

If we navigate to the "Page Template (MVC)" module in Kentico, we can see a list of all the Custom Page Templates we've created.

![A list of the single "Landing Page with Content" Custom Landing Page](https://dev-to-uploads.s3.amazonaws.com/i/6jur5ljw76lx5up00obz.jpg)

The functionality is pretty limited here, with deletion being the only real meaningful action.

---

## Coding an MVC Page Template Controller

Let's look at the code used in the above screen captures to get an idea of what is required to create MVC Page Templates.

We're going to use Controller-based Page Templates, as they show more of the API and setup, rather than the simpler View-only Page Templates.

### MVC Controller

First, we need a normal MVC Controller that is routed to when the Page Template Page is visited:

```csharp
public class LandingPageController : Controller
{
    public ActionResult Index()
    {
        var page = DocumentHelper
            .GetDocuments()
            .Path("/Landing-Page")
            .OnCurrentSite()
            .TopN(1)
            .FirstOrDefault();

        return page is null
            ? HttpNotFound() as ActionResult
            : new TemplateResult(page.DocumentID);
    }
}
```

The key here is returning a `new TemplateResult()` with the `DocumentID` of the Page using Page Templates.

### Page Template Controllers

Next, we define some Page Template Controllers. Our first doesn't have any defined properties, so it's really simple:

```csharp
public class LandingPageBasicTemplateController 
    : PageTemplateController
{
    public ActionResult Index() => 
        View("_BasicTemplate");
}
```

We inherit from `PageTemplateController` and define a normal `Index()` action method that returns the View defined for this Page Template.

> This part is key 🔑 to understanding how to implement MVC Page Templates. The first Controller (`LandingPageController`) receives the request and allows Kentico to intercept it by returning a `TemplateResult`.

> Then, based on the Page Template selected, Kentico calls the correct `PageTemplateController` to render the selected Page Template (MVC View).

> When using Page Templates with custom Controllers or properties, we will always have at least 2 Controllers - 1 for the route and 1 for the rendering 😎.

Our second Page Template Controller has the "Show Hero" property, so the implementation is slightly more complex:

```csharp
public class LandingPageHeroTemplateController :
    PageTemplateController<LandingPageHeroTemplateProperties>
{
    public ActionResult Index() =>
        View("_HeroTemplate", new LandingPageHeroTemplateViewModel
        {
            ShowHero = GetProperties().ShowHero
        });
}

public class LandingPageHeroTemplateProperties :
    IPageTemplateProperties
{
    [EditingComponent(
        CheckBoxComponent.IDENTIFIER, 
        Label = "Show Hero")]
    public bool ShowHero { get; set; } = true;
}

public class LandingPageHeroTemplateViewModel
{
    public bool ShowHero { get; set; }
}
```

We define a Controller class that inherits `PageTemplateController<T>` where `T` is a class implementing `IPageTemplateProperties`.

The `GetProperties()` method comes from `PageTemplateController<T>`.

The Page Template properties class works the same as properties classes for Widgets or Widget Sections 😉.

Finally we define a view model to pass our property value from the Controller to the View 👍🏾.

### Page Template Views

The Views for our 2 Page Templates are simple.

> Note the location for the View files for both Controllers.

> Although we are using 2 new Controller classes to render the Page Template views, the MVC request is being handled in the context of the `LandingPageController`.

> Therefore, the files, following MVC convention, are located under `~/Views/LandingPage` 🤓:

```html
<!-- ~/Views/LandingPage/_BasicTemplate.cshtml -->

<div class="section">
    <div class="row">
        <div class="col d-flex justify-content-center">
            <p>
                This is a landing page basic template.
            </p>
        </div>
    </div>
</div>

@Html.Kentico().EditableArea("landing-page-bottom")
```

and

```html
<!-- ~/Views/LandingPage/_HeroTemplate.cshtml -->

@model Sandbox.Controllers.LandingPageHeroTemplateViewModel

@if (Model.ShowHero)
{
    <div class="jumbotron jumbotron-fluid">
        <div class="container">
            <h1 class="display-4">Fluid jumbotron</h1>
            <p class="lead">Lorem Ipsum.</p>
        </div>
    </div>
}

<div class="section">
    <div class="row">
        <div class="col d-flex justify-content-center">
            <p>
                This is a landing page hero template.
            </p>
        </div>
    </div>
</div>

@Html.Kentico().EditableArea("landing-page-bottom")
```

### Page Template Registration

The final bit of code are the `[RegisterPageTemplate()]` assembly attributes that register our Page Templates with Kentico so that they appear in the Page Template selection dialog:

```csharp
[assembly: RegisterPageTemplate(
    "sandbox.landing-page.hero",
    typeof(LandingPageHeroTemplateController), 
    "Landing Page Hero")]

[assembly: RegisterPageTemplate(
    "sandbox.landing-page.basic",
    typeof(LandingPageBasicTemplateController), 
    "Landing Page Basic")]
```

Copying this code into your Kentico 12 MVC application should have you up and running with some cool 😎 MVC Page Templates that you can play around 👏🏾 with and [enhance](https://www.youtube.com/watch?v=Vxq9yj2pVWk).

## Conclusion

So, now we've peered deep 👾 into the beautiful abyss of Kentico 12 MVC Page Templates.

We've defined what they really are - a convenient way to let content managers pick the MVC View for rendering content - and the various common use-cases we might implement them for.

We've also covered the additional features that Page Templates bring to our sites - properties, filtering, and Custom Page Templates.

We even looked at how Kentico stores Page Template data and creates new Custom Page Templates in the database 🤓.

Finally, we stepped through the process of creating some simple Page Templates for our Landing Page.

I hope this overview of MVC Page Templates helps clarify any confusion you've had about this cool 😎 technology (I wish I had a blog post like this to read when I was trying to figure them out 😅!)

As always, thanks for reading 🙏!

---

<figcaption>Photo by <a href="https://unsplash.com/@tim_arterbury">Tim Arterbury</a> on <a href="https://unsplash.com">Unsplash</a></figcaption>

---

We've put together a list over on [Kentico's GitHub account](https://github.com/Kentico/Home/blob/master/RESOURCES.md) of developer resources. Go check it out!

If you are looking for additional Kentico content, checkout the Kentico tag here on DEV:

{% tag kentico %}

Or my Kentico blog series:

- [Kentico EMS: MVC Widget Experiements](https://dev.to/search?q=kentico%20ems%3A%20mvc%20widget%20experiements)
- [Kentico 12: Design Patterns](https://dev.to/search?q=Kentico%2012%3A%20Design%20Patterns)
- [Kentico CMS Quick Tips](https://dev.to/search?q=Kentico%20CMS%20Quick%20Tip)