Module: Xperience by Kentico Developer kickstart

7 of 13 Pages

Build a page template

We recommend using Page templates to display content in website projects. They enable flexibility in the presentation of a page without developer intervention – you can set up multiple templates for editors to choose from, and include properties that allow them to configure the design.

Now that we have created a Landing page content type and configured the project, let’s create a simple template to display landing pages. The template will access fields from the reusable Slogan item linked by the Landing page. 

In the Kickstart.Web project, create a directory Features, with a subfolder LandingPages for code files relating to landing pages.

Add a view model class

Let’s start by defining a view model class to hold the data the template should display.

Add a new class named LandingPageViewModel to the LandingPages folder, with a Message property to represent some text that should be displayed on the page.

Then add a GetViewModel method that takes a LandingPage as the parameter. It should use the SloganText of the linked Slogan item for the Message property.

C#
LandingPageViewModel.cs


using System.Linq;

namespace Kickstart.Web.Features.LandingPages;

public class LandingPageViewModel
{
    public string Message { get; set; } = string.Empty;

    public static LandingPageViewModel GetViewModel(LandingPage landingPage) =>
        new()
        {
            Message = landingPage?.LandingPageSlogan.FirstOrDefault()?.SloganText ?? string.Empty
        };
}

Define a page template controller

Page templates use a ComponentViewModel object as a model by default. This is useful for accessing any page template properties you may have set up, but adds an extra step to accessing content item data.

Let’s create a controller that allows you to substitute your own LandingPageViewModel instead, so that you can use it directly in the view.

Add the class

Create a new class called LandingPageController in the Features/LandingPages folder of Kickstart.Web.

Then add an asynchronous Index action for the controller, which returns a TemplateResult object.

C#
LandingPageController.cs


using System.Threading.Tasks;
using Kentico.PageBuilder.Web.Mvc.PageTemplates;

using Microsoft.AspNetCore.Mvc;

namespace Kickstart.Web.Features.LandingPages;

public class LandingPageController : Controller
{
    public async Task<IActionResult> Index()
    {
        return new TemplateResult();
    }
}

Query the landing page

To retrieve the data of a given landing page, we’ll use the ContentRetriever API.

Inject the content retriever service into your class.

Utilize its RetrieveCurrentPage method to fetch the data of your current Landing page. This method will automatically find the page associated with the request route, retrieve the data in the current language, and map it to a LandingPage object in code.

Once you retrieve the landing page data, you can use the GetViewModel method from earlier in this step to create a LandingPageViewModel.

C#
LandingPageController.cs

using System.Threading.Tasks;

using Kentico.Content.Web.Mvc;
using Kentico.PageBuilder.Web.Mvc.PageTemplates;

using Microsoft.AspNetCore.Mvc;

namespace Kickstart.Web.Features.LandingPages;

public class LandingPageController : Controller
{
    private readonly IContentRetriever contentRetriever;

    public LandingPageController(
        IContentRetriever contentRetriever) => this.contentRetriever = contentRetriever;

    public async Task<IActionResult> Index()
    {
        var parameters = new RetrieveCurrentPageParameters
        {
            LinkedItemsMaxLevel = 1
        };
        var page = await contentRetriever.RetrieveCurrentPage<LandingPage>(parameters);
        var model = LandingPageViewModel.GetViewModel(page);
        return new TemplateResult(model);
    }
}

Register the controller

Now we need to tell Xperience to use this template whenever someone requests a page of the LandingPage type.

Use the RegisterWebPageRoute assembly attribute to create this association.

Thanks to this attribute, the content tree-based router (which you configured in the previous step) knows to use the controller.

You don’t need to set up any kind of routing table that references the controller.

C#
LandingPageController.cs

using Kentico.Content.Web.Mvc.Routing;
using Kickstart;

[assembly: RegisterWebPageRoute(
    contentTypeName: LandingPage.CONTENT_TYPE_NAME,
    controllerType: typeof(Kickstart.Web.Features.LandingPages.LandingPageController))]

namespace Kickstart.Web.Features.LandingPages;
...

The completed file should look like this code in the Kickstart repository.

Refactoring

The code samples here are meant to demonstrate important principles, but they are not production-ready.

In real-world scenarios, you will need to retrieve various content items frequently in your project. We recommend extracting content querying functionality into a separate service to make your code more modular and readable, as in in this example.

Depending on the size and lifetime of projects, you may also want to consider more complex enterprise architecture with a higher degree of abstraction.

Add the page template view

With the view model and controller in place, let’s move on to the view.

In the Features/LandingPages folder, create an empty Razor view called LandingPagePageTemplate.cshtml.

Designate the view’s model as TemplateViewModel. Then retrieve the LandingPageViewModel object from the controller by calling Model.GetTemplateModel.

Finally, display the model’s message and add a Page Builder editable area.

cshtml
LandingPagePageTemplate.cshtml


@using Kickstart.Web.Features.LandingPages

@model TemplateViewModel

@{
    var templateModel = Model.GetTemplateModel<LandingPageViewModel>();
}

<h3>@templateModel.Message</h3>

<editable-area area-identifier="areaMain" />

The TemplateViewModel lives in the Kentico.Content.Web.Mvc.PageBuilder namespace. Notice that we don’t need a using directive here because we added it to _ViewImports.cshtml in the previous step.

Register the page template

Now the landing page template exists in code, but Xperience cannot use it unless you register it.

In the current state, when execution hits your controller, Xperience will not know which view to use when the Index action returns TemplateResult.

To fix this, let’s create a new file to represent the template itself.

Set up the template file

Add a new file to the Kickstart.Web/Features/LandingPages folder named LandingPagePageTemplate.cs.

Define a class of the same name and add a string constant to represent a unique identifier for the template.

C#
LandingPagePageTemplate.cs

namespace Kickstart.Web.Features.LandingPages;
public static class LandingPagePageTemplate
{
    public const string IDENTIFIER = "Kickstart.LandingPagePageTemplate";
}

Add the registration attribute

Now we can use the IDENTIFIER constant to register the page template with the Xperience API.

Use the RegisterPageTemplate attribute, which takes the following parameters:

  • The identifier of the template, which Xperience will use when serializing template data in the database.
  • The display name for the template in the admin UI.
  • The path to the template’s view file.
  • A list of content types that the template supports.
  • An icon to represent the template in the admin UI.

If you don’t provide a list of allowed types, the template is allowed for all web page content types by default.

C#
LandingPagePageTemplate.cs


using Kentico.PageBuilder.Web.Mvc.PageTemplates;

using Kickstart;
using Kickstart.Web.Features.LandingPages;

[assembly: RegisterPageTemplate(
    identifier: LandingPagePageTemplate.IDENTIFIER,
    name: "Landing page content type template",
    customViewName: "~/Features/LandingPages/LandingPagePageTemplate.cshtml",
    ContentTypeNames = [LandingPage.CONTENT_TYPE_NAME],
    IconClass = "xp-market")]

namespace Kickstart.Web.Features.LandingPages;
public static class LandingPagePageTemplate
{
    public const string IDENTIFIER = "Kickstart.LandingPagePageTemplate";
}

Now the system knows that the view from the previous section is a page template. It will be available to any LandingPage pages that are allowed to use page templates.

Learn more about the RegisterPageTemplate attribute on this page of our documentation

In the next step, let’s check your progress by creating a homepage that uses this template.