Adding page Templates to a page type

Hosam Abdeltawab asked on August 25, 2020 22:59

I created a page type called simplePage. I want to add multiple page templates to use whenever I create a new page of that type. Here are the steps I followed:

  1. Set the URL pattern on the page-type as /{%NodeAlias%}
  2. Created a partial view for the template (_SimplePageTemplate.cshtml)
  3. Created 2 controllers and one property files (PageTemplateController.cs, SimplePageTemplateController.cs, SimplePageTemplateProperties.cs)
  4. Registered the page template

When I create a new page with the page-type simplePage, it doesn't give me an option to choose a page template? How would I be able to choose/see the templates I created?

Here is the code for the files:

  • _SimplePageTemplate.cshtml:

    @section styles{ @Html.Kentico().PageBuilderStyles()}
    @section scripts{ @Html.Kentico().PageBuilderScripts()}
    @{ Layout = "~/Views/Shared/_Layout.cshtml"; }
    @Html.Kentico().EditableArea("maincontent")
    
  • PageTemplateController.cs:

    using CMS.DocumentEngine;
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace AE.Web.Gwic.Controllers
    {
        public class PageTemplateController : Controller
        {
            /// <summary>
            /// A GET action displaying the page where you wish to use page templates.
            /// </summary>
            /// <param name="pageAlias">Page alias of the displayed page.</param>
            public ActionResult Index(string pageAlias)
            {
                // Retrieves the page from the Kentico database
                TreeNode page = DocumentHelper.GetDocuments()
                    .WhereEquals("NodeAlias", pageAlias)
                    .OnCurrentSite()
                    .TopN(1)
                    .FirstOrDefault();
    
                // Returns a 404 error when the retrieving is unsuccessful
                if (page == null)
                {
                    return HttpNotFound();
                }
    
                // Returns a TemplateResult object, created with an identifier of the page as its parameter
                // Automatically initializes the page builder feature for any editable areas placed within templates
                return new TemplateResult(page.DocumentID);
            }
        }
    }
    
  • SimplePageTemplateController.cs:

    using AE.Web.Gwic.Controllers.PageTemplates;
    using AE.Web.Gwic.Models.PageTemplates;
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    [assembly: RegisterPageTemplate("AE.Gwic.Web.PageTemplates.SimplePageTemplate", typeof(SimplePageTemplateController), "Simple Page")]
    
    namespace AE.Web.Gwic.Controllers.PageTemplates
    {
        public class SimplePageTemplateController : PageTemplateController<SimplePageTemplateProperties>
        {
            // GET: SimplePageTemplate
            public ActionResult Index()
            {
                return View("_SimplePageTemplate");
            }
        }
    }
    
  • SimplePageTemplateProperties.cs:

    using Kentico.Forms.Web.Mvc;
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    
    namespace AE.Web.Gwic.Models.PageTemplates
    {
        public class SimplePageTemplateProperties : IPageTemplateProperties
        {
            [EditingComponent(CheckBoxComponent.IDENTIFIER, Order = 0, Label = "Show Header")]
            public bool? ShowHeader { get; set; } = true;
        }
    }
    

Can someone tell me what am I missing?

Correct Answer

Liam Goldfinch answered on August 26, 2020 23:23

Hi Hosam,

TwoColumnPageTemplateController and SimplePageTemplateController should inherit from PageTemplateController<PageTemplateProperties> not your BasePageTemplateController class, can you try again with that?

BasePageTemplateController should inherit from just Controller

0 votesVote for this answer Unmark Correct answer

Recent Answers


Liam Goldfinch answered on August 26, 2020 01:43 (last edited on August 26, 2020 01:47)

Hi Hosam,

If there's only one Page Template available, Kentico automatically assigns that when creating the page. In your example code above you're only registering one Page Template.

To get the template selector when creating a new page, you need to either:

  • Add a 2nd Page Template Controller and view for it (e.g. another controller like SimplePageTemplateController) so Kentico has two template options to display.
  • Or, once you've created your first page with the registered Page Template, configure the page slightly to test (maybe add a widget or text to the page) and hit the Save as template button in the top right, looks like this:

Image Text

This will add a Custom template for selection like this:

Image Text

Both of these options will add the Change template button at the bottom left of the page builder area: Image Text

Once this is all working, you will probably want to filter the page templates so they only appear for the Page Type you want, follow the documentation here: https://docs.kentico.com/k12sp/developing-websites/page-builder-development/developing-page-templates-in-mvc/filtering-page-templates-in-mvc

1 votesVote for this answer Mark as a Correct answer

Hosam Abdeltawab answered on August 26, 2020 18:29

Liam,

I added another template called, TwoColumnPageTemplate, and I didn't get the option to choose which template to use when I created a new page? I didn't update any routes or anything. I just added another controller and view.

Controller:

    using AE.Web.Gwic.Models.PageTemplates;
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using System.Web.Mvc;

    [assembly: RegisterPageTemplate("AE.Gwic.Web.PageTemplates.TwoColumnPageTemplate", typeof(PageTemplateProperties), "Two Column Page")]

    namespace AE.Web.Gwic.Controllers.PageTemplates
    {
        public class TwoColumnPageTemplateController : PageTemplateController<PageTemplateProperties>
        {
            public ActionResult Index()
            {
                return View("PageTemplates/_TwoColumnPageTemplate");
            }
        }
    }

View:

    @section styles{ @Html.Kentico().PageBuilderStyles()}
    @section scripts{ @Html.Kentico().PageBuilderScripts()}
    @{ Layout = "~/Views/Shared/_Layout.cshtml"; }

    <div class="row">
        <div class="col-md-6">
            @Html.Kentico().EditableArea("maincontent")
        </div>
        <div class="col-md-6">
            @Html.Kentico().EditableArea("maincontent2")
        </div>
    </div>

PageTemplateProperties:

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

    namespace AE.Web.Gwic.Models.PageTemplates
    {
        public class PageTemplateProperties : IPageTemplateProperties
        {
            [EditingComponent(CheckBoxComponent.IDENTIFIER, Order = 0, Label = "Show Header")]
            public bool? ShowHeader { get; set; } = true;
        }
    }

Do I need to initialize the page?

0 votesVote for this answer Mark as a Correct answer

Liam Goldfinch answered on August 26, 2020 19:00

Hi Hosam,

It might be that the controller is being registered incorrectly?

[assembly: RegisterPageTemplate("AE.Gwic.Web.PageTemplates.TwoColumnPageTemplate", typeof(PageTemplateProperties), "Two Column Page")]

needs to be:

[assembly: RegisterPageTemplate("AE.Gwic.Web.PageTemplates.TwoColumnPageTemplate", typeof(TwoColumnPageTemplateController), "Two Column Page")]
0 votesVote for this answer Mark as a Correct answer

Hosam Abdeltawab answered on August 26, 2020 19:19

Hey Liam,

That fixed it; however, after I create the page, I am getting a 404 error: Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly. Requested URL: /test-page-two-column

I think what caused that is the routes are not correctly configured. What are your inputs?

0 votesVote for this answer Mark as a Correct answer

Liam Goldfinch answered on August 26, 2020 19:46

Hi Hosam,

Do you have any routing setup at all? What do you have in your RouteConfig?

Are you trying to route based on a document's NodeAliasPath? You could try something like:

        routes.MapRoute(
            "Dynamic",
            "{*pageAlias}",
            new { controller = "PageTemplate", action = "Index" });
0 votesVote for this answer Mark as a Correct answer

Hosam Abdeltawab answered on August 26, 2020 20:10

I added that, but still to no end. The page template controller is from Kentico.PageBuilder.Web.Mvc.PageTemplates and doesn't have an index function.....

0 votesVote for this answer Mark as a Correct answer

Liam Goldfinch answered on August 26, 2020 20:21

Ah well that's not ideal having your PageTemplateController in your original post (which does have an index) named the same as Kentico's Controller. I suggest renaming that, and change the route I provided with the new controller name.

Also, for the Page Type you're using, have you set the URL Pattern?

0 votesVote for this answer Mark as a Correct answer

Hosam Abdeltawab answered on August 26, 2020 20:28

yes, I am using /{%NodeAlias%} as the url pattern

0 votesVote for this answer Mark as a Correct answer

Liam Goldfinch answered on August 26, 2020 20:59

Have you debugged your controller here:

        // Retrieves the page from the Kentico database
        TreeNode page = DocumentHelper.GetDocuments()
            .WhereEquals("NodeAlias", pageAlias)
            .OnCurrentSite()
            .TopN(1)
            .FirstOrDefault();

        // Returns a 404 error when the retrieving is unsuccessful
        if (page == null)
        {
            return HttpNotFound();
        }

        // Returns a TemplateResult object, created with an identifier of the page as its parameter
        // Automatically initializes the page builder feature for any editable areas placed within templates
        return new TemplateResult(page.DocumentID);

Is page null here, and returning a HttpNotFound?

0 votesVote for this answer Mark as a Correct answer

Hosam Abdeltawab answered on August 26, 2020 22:56

Liam,

I have added a breakpoint at the basePageTemplate controller and added a new route to that controller. The break point isn't being hit. Here is the code:

PageTemplateProperites.cs

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

    namespace AE.Web.Gwic.Models.PageTemplates
    {
        public class PageTemplateProperties : IPageTemplateProperties
        {
            [EditingComponent(CheckBoxComponent.IDENTIFIER, Order = 0, Label = "Show Header")]
            public bool? ShowHeader { get; set; } = true;
        }
    }

PageTemplateController

    namespace Kentico.PageBuilder.Web.Mvc.PageTemplates
    {
        //
        // Summary:
        //     Base class for Page builder page template controller with custom properties of
        //     type TPropertiesType.
        public abstract class PageTemplateController<TPropertiesType> : ComponentController<TPropertiesType> where TPropertiesType : class, IPageTemplateProperties, new()
        {
            //
            // Summary:
            //     Creates an instance of Kentico.PageBuilder.Web.Mvc.PageTemplates.PageTemplateController`1
            //     class.
            protected PageTemplateController();
            //
            // Summary:
            //     Creates an instance of Kentico.PageBuilder.Web.Mvc.PageTemplates.PageTemplateController`1
            //     class.
            //
            // Parameters:
            //   propertiesRetriever:
            //     Retriever for page template properties.
            //
            //   currentPageRetriever:
            //     Retriever for current page where the page template is used.
            //
            // Remarks:
            //     Use this constructor for tests to handle dependencies.
            protected PageTemplateController(IComponentPropertiesRetriever<TPropertiesType> propertiesRetriever, ICurrentPageRetriever currentPageRetriever);
        }
    }

BaseTemplateController.cs

    using Kentico.PageBuilder.Web.Mvc;
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using Kentico.Web.Mvc;
    using System.Linq;
    using System.Web.Mvc;

    namespace AE.Web.Gwic.Controllers
    {
        public class BasePageTemplateController : PageTemplateController<PageTemplateProperties>
        {
            /// <summary>
            /// A GET action displaying the page where you wish to use page templates.
            /// </summary>
            /// <param name="pageAlias">Page alias of the displayed page.</param>
            public ActionResult Index(string pageAlias)
            {
                // Retrieves the page from the Kentico database
                TreeNode page = DocumentHelper.GetDocuments()
                    .WhereEquals("NodeAlias", pageAlias)
                    .OnCurrentSite()
                    .TopN(1)
                    .FirstOrDefault();

                // Returns a 404 error when the retrieving is unsuccessful
                if (page == null)
                {
                    return HttpNotFound();
                }

                // Initializes the page builder with the DocumentID of the page
                HttpContext.Kentico().PageBuilder().Initialize(page.DocumentID);

                // Returns a TemplateResult object, created with an identifier of the page as its parameter
                // Automatically initializes the page builder feature for any editable areas placed within templates
                return new TemplateResult(page.DocumentID);
            }
        }
    }

TwoColumnPageTemplateController.cs

    using AE.Web.Gwic.Controllers.PageTemplates;
    using Kentico.PageBuilder.Web.Mvc.PageTemplates;
    using System.Web.Mvc;

    [assembly: RegisterPageTemplate("AE.Gwic.Web.PageTemplates.TwoColumnPageTemplate", typeof(TwoColumnPageTemplateController), "Two Column Page")]

    namespace AE.Web.Gwic.Controllers.PageTemplates
    {
        public class TwoColumnPageTemplateController : BasePageTemplateController
        {
            public ActionResult Index()
            {
                return View("PageTemplates/_TwoColumnPageTemplate");
            }
        }
    }

RouteConfig.cs

    using Kentico.Web.Mvc;
    using System.Web.Mvc;
    using System.Web.Routing;

    namespace AE.Web.Gwic
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

                // Maps routes to Kentico HTTP handlers and features enabled in ApplicationConfig.cs
                // Always map the Kentico routes before adding other routes. Issues may occur if Kentico URLs are matched by a general route, for example images might not be displayed on pages
                routes.Kentico().MapRoutes();

                routes.MapRoute(
                    name: "Templates",
                    url: "{pageAlias}",
                    defaults: new { controller = "BasePageTemplate", action = "Index" }
                    );

                routes.MapRoute(
                    "Default",
                    "{controller}/{action}/{id}",
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                );
            }
        }
    }

This gives me a 500 error

0 votesVote for this answer Mark as a Correct answer

Hosam Abdeltawab answered on August 26, 2020 23:54

That worked. Thanks!

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.