---
title: Define the template's properties
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

### Define page template properties

Now that we have view models to determine the service template's data, let's add properties, so that editors can configure its appearance.

The properties will utilize dropdowns fed by the dropdown provider we created [earlier in this series](https://docs.kentico.com/modules/page-builder/map-enum-to-dropdown.md), so start by defining enumerations for different color scheme and corner style options.

> **Tip:** Decorate options with the `Description` attribute to provide user-friendly names.

- In the _\~/Features/Shared/OptionProviders/ColorScheme_ directory:
  ```csharp title="ColorSchemeOption.cs"
      using System.ComponentModel;

      namespace TrainingGuides.Web.Features.Shared.OptionProviders.ColorScheme;

      public enum ColorSchemeOption
      {
          [Description("Light background, dark text")]
          Light1 = 1,

          [Description("Light background, dark text 2")]
          Light2 = 2,

          [Description("Light background, dark text 3")]
          Light3 = 3,

          [Description("Transparent background, dark text")]
          TransparentDark = 4,

          [Description("Transparent background, medium text")]
          TransparentMedium = 5,

          [Description("Transparent background, light text")]
          TransparentLight = 6,

          [Description("Dark background, light text")]
          Dark1 = 7,

          [Description("Dark background, light text 2")]
          Dark2 = 8
      }
  ```
- In the _\~/Features/Shared/OptionProviders/CornerStyle_ directory:

  ```csharp title="CornerStyleOption.cs"
      using System.ComponentModel;

      namespace TrainingGuides.Web.Features.Shared.OptionProviders.CornerStyle;

      public enum CornerStyleOption
      {
          [Description("Sharp corners")]
          Sharp = 0,
          [Description("Round corners")]
          Round = 1,
          [Description("Very round corners")]
          VeryRound = 2,
      }
  ```

Next, create a properties class for the _ServicePage_ content type that utilizes these dropdowns in the _\~/Features/FinancialServices_ folder.

```csharp title="ServicePagePageTemplateProperties.cs"
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using Kentico.Xperience.Admin.Base.FormAnnotations;
    using TrainingGuides.Web.Features.Shared.OptionProviders;
    using TrainingGuides.Web.Features.Shared.OptionProviders.CornerStyle;
    using TrainingGuides.Web.Features.Shared.OptionProviders.ColorScheme;

    namespace TrainingGuides.Web.Features.FinancialServices;

    public class ServicePagePageTemplateProperties : IPageTemplateProperties
    {
        [DropDownComponent(
            Label = "Color scheme",
            ExplanationText = "Select the color scheme of the template.",
            DataProviderType = typeof(DropdownEnumOptionProvider<ColorSchemeOption>),
            Order = 20)]
        public string ColorScheme { get; set; } = nameof(ColorSchemeOption.TransparentDark);

        [DropDownComponent(
            Label = "Corner style",
            ExplanationText = "Select the corner type of the template.",
            DataProviderType = typeof(DropdownEnumOptionProvider<CornerStyleOption>),
            Order = 30)]
        public string CornerStyle { get; set; } = nameof(CornerStyleOption.Round);
    }
```

### Set up the template

With the view models and service in place, we can create the page template, register it, and serve it from a controller.

> **Tip:** **Find more details here**
>
> This section briefly goes over processes covered in [Build a page template](https://docs.kentico.com/guides/development/developer-kickstart/build-a-page-template.md) step of our Kickstart series. Please refer to it if you'd like more detailed steps and information in the context of a different example.
>
> Note these sections in particular:
>
> - [Add the page template view](https://docs.kentico.com/guides/development/developer-kickstart/build-a-page-template.md#add-the-page-template-view)
> - [Register the page template](https://docs.kentico.com/guides/development/developer-kickstart/build-a-page-template.md#register-the-page-template)
> - [Define a page template controller](https://docs.kentico.com/guides/development/developer-kickstart/build-a-page-template.md#define-a-page-template-controller)

#### Define the view

With the view model and properties in place, you can create a view under _\~/Features/FinancialServices_.

Use the `GetTemplateModel` method to retrieve structured data and display it in a view. We'll expand on this in the future. For now, let's keep it simple.

```cshtml title="ServicePagePageTemplate.cshtml"
    @using TrainingGuides.Web.Features.FinancialServices.Models
    @using TrainingGuides.Web.Features.FinancialServices

    @model TemplateViewModel<ServicePagePageTemplateProperties>

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

    <div>
        <div>
            <h3>@templateModel.NameHtml</h3>
            <p>@templateModel.ShortDescriptionHtml</p>
        </div>
        
        <div>
            <img src="@templateModel.Media.FirstOrDefault()?.FilePath" alt="@templateModel.Media.FirstOrDefault()?.Description"/>
        </div>
    </div>
```

#### Register the template

Create a new file called _ServicePagePageTemplate.cs_ in the _\~/Features/FinancialServices_ folder, and use it to house the registration attribute for the page template.

```csharp title="ServicePagePageTemplate.cs"
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using TrainingGuides;
    using TrainingGuides.Web.Features.FinancialServices;

    [assembly: RegisterPageTemplate(
        identifier: ServicePagePageTemplate.IDENTIFIER,
        name: "Service page template",
        propertiesType: typeof(ServicePagePageTemplateProperties),
        customViewName: "~/Features/FinancialServices/ServicePagePageTemplate.cshtml",
        ContentTypeNames = [ServicePage.CONTENT_TYPE_NAME],
        IconClass = "xp-box")]

    namespace TrainingGuides.Web.Features.FinancialServices;

    public static class ServicePagePageTemplate
    {
        public const string IDENTIFIER = "TrainingGuides.ServicePageTemplate";
    }
```

#### Create the controller

1. In the _\~/Features/FinancialServices_ folder, add a file called _ServicePageController_.
2. Use an `IContentItemRetrieverService` to get the service data from Xperience.
3. Use an instance of the `IServicePageService` we defined [earlier](https://docs.kentico.com/modules/page-builder/model-template-data.md#add-a-new-.net-service) to convert the `ServicePage` to a `ServicePageViewModel`.
4. Add a new `ServiceFeatureViewModel` containing the service's price, so that it appears in the table.

```csharp title="ServicePageController.cs"
using Kentico.Content.Web.Mvc.Routing;
using Kentico.PageBuilder.Web.Mvc.PageTemplates;
using Microsoft.AspNetCore.Mvc;
using TrainingGuides;
using TrainingGuides.Web.Features.FinancialServices.Models;
using TrainingGuides.Web.Features.FinancialServices.Services;
using TrainingGuides.Web.Features.Shared.Services;

[assembly: RegisterWebPageRoute(
    contentTypeName: ServicePage.CONTENT_TYPE_NAME,
    controllerType: typeof(TrainingGuides.Web.Features.FinancialServices.ServicePageController))]

namespace TrainingGuides.Web.Features.FinancialServices;

public class ServicePageController(
    IContentItemRetrieverService contentItemRetriever,
    IServicePageService servicePageService) : Controller
{
    public async Task<IActionResult> Index()
    {
        var servicePage = await contentItemRetriever.RetrieveCurrentPage<ServicePage>(3);

        var model = await servicePageService.GetServicePageViewModel(servicePage);
        model.Features.Add(
                new ServiceFeatureViewModel
                {
                    Key = "price-from-service-content-item",
                    Name = "Price",
                    LabelHtml = new("Price"),
                    Price = model.Price,
                    ValueHtml = new(string.Empty),
                    FeatureIncluded = false,
                    ValueType = ServiceFeatureValueType.Number,
                    ShowInComparator = true,
                });

        return new TemplateResult(model);
    }
}
```

#### Check your progress

We've been focused on code for a while, so let's double-check that everything is working on the site.

1. Sign in to the Xperience admin and open the _Training guides pages_ channel.
2. Choose one of the _Service page_ pages under the _Services_ page in the tree, and edit the page on the _Page Builder_ tab.
3. Click the page icon in the bottom left corner of the Page Builder frame to configure the Page Builder properties.
4. Choose the _Service page template_, and see how the data from the service page is now displayed according to your templates.

🎬 [Video](https://docs.kentico.com/docsassets/modules/define-template-properties/VideoTemplateProgress.mp4)

> **Tip:** If you're not seeing any output, make sure the service page type is included in the `UsePageBuilder` call during the application's startup sequence, try putting breakpoints in the controller and view. If one or both of them is not being hit, it could indicate an issue in one of the registration attributes for the controller or page template.
