Enabling content tree-based routing

Content tree-based routing needs to be enabled in both the live site application and the Settings application in the administration interface.

If you are switching to content tree-based routing from custom routing with page type URL patterns, you can manually preserve the former URLs to make the transition smoother. The URLs need to be preserved before you enable content tree-based routing.

Xperience administration application

The Xperience administration application needs to have its Routing mode set to Based on content tree. New installations of Xperience have this mode set by default:

Changing routing modes

Changing the routing mode to Based on content treeor configuring some of the optional settings causes the system to (re)generate a URL for every suitable page, so the operation may be time-consuming (depending on the performance of the hosting environment).

When changing the routing mode back to Custom, the system deletes all generated URLs. Make sure you register appropriate routes into your live site application’s routing table before transitioning, otherwise your website will stop working correctly.

  1. Open the Settings application in the Xperience administration application.
  2. Switch to the URLs and SEO tab.
  3. Under the Routing section, select Based on content tree for the Routing mode setting.
    • The setting is site-specific – each site can be configured to use a different routing mode.
  4. (Optional) Under the Content tree-based routing section:
    • Set the Home page and Home page URL behavior settings to let the system handle redirection to your website home page. Using a unified home page URL is highly recommended, because it prevents the duplicate content problem on your website’s most important URL.
    • Set the URL format for multilingual sitessetting, to determine the format in which page URLs are generated on multilingual sites.
    • Configure the Enforce lowercase URLs setting to ensure lowercasing of the virtual (relative) parts of URLs. By default, the system generates URLs in a lowercase format.
    • Set the Use URLs with trailing slash setting to specify how the trailing slash is handled in URLs.
    • Enable the Store former URLs setting if you want the system to keep track of changes made to page URLs and perform redirects from former to current URLs.
      • To prevent accumulation of various temporary URLs as former URLs, we recommend enabling this setting only on live websites (i.e. production environments).
  5. Save the changes.

The administration application is now configured to use content tree-based routing.

Live site application

On the side of the live site application, you need to enable content tree-based routing as a feature used by your project.

  1. Open your MVC project in Visual Studio.

  2. Enable the page routing feature at the start of your application’s life cycle, for example in the Application_Start method of your project’s Global.asax file.

    MVC projects created by the installer contain the ApplicationConfig class, whose RegisterFeatures method is called in the Application_Start method by default. You can use this class to encapsulate all of your ApplicationBuilder code (enabling and configuring of Xperience MVC features).

    Note: The feature must be enabled before you register routes into the application’s RouteTable. The Kentico().MapRoutes() method adds routes that handle automatic routing when the feature is enabled.

  3. Call the UsePageRouting method of the ApplicationBuilder instance.

    
    
    
     using Kentico.Content.Web.Mvc.Routing;
     using Kentico.Web.Mvc;
    
     ...
    
     protected void Application_Start()
     {
         ...
    
         // Gets the ApplicationBuilder instance
         // Allows you to enable and configure selected Xperience MVC integration features
         ApplicationBuilder builder = ApplicationBuilder.Current;
    
         // Enables content tree-based routing
         builder.UsePageRouting();
    
         ...
     }
    
    
     

Content tree-based routing is now enabled for the live site application. The Kentico().MapRoutes() method called in your application’s RouteConfig registers a general route that matches URLs generated by the system for page types with the URL feature enabled.

  1. Open your live site project in Visual Studio.

  2. Edit your application’s startup class (Startup.cs by default).

  3. Enable the page routing feature by:

    1. Calling the UsePageRouting method of the IFeaturesBuilder delegate passed to the IServiceCollection.AddKentico method within ConfigureServices.

    2. Enabling membership features for the application (required due to authorization checks performed by the routing feature). 

      
      
      
       using Kentico.Content.Web.Mvc.Routing;
       using Kentico.Web.Mvc;
      
       ...
      
       public void ConfigureServices(IServiceCollection services)
       {
           ...
           // Enables and configures Xperience features
           services.AddKentico(features =>
           {
               // Enables content tree-based routing
               features.UsePageRouting();
               ... 
           });
      
           // Membership configuration
           ...
       }
      
      
       

Content tree-based routing is now enabled for the live site application. The Kentico().MapRoutes() method called in your application’s startup pipeline registers a general route that matches URLs generated by the system for page types with the URL feature enabled.

Continue by configuring your project.

Preserving former URLs when switching to content tree-based routing

If you want to enable content tree-based routing on a site that uses customrouting based on page type URL patterns, and you want to make sure the pages are still accessible under the old “custom” URLs, you can use the following code snippet to preserve the old URLs as former URLs. The code stores your URLs in the table for the Former URLs application and maps them to the corresponding pages in the content tree. This ensures that when requested, the old URLs are redirected to their corresponding new URLs (once you enable content tree-based routing and the former URLs feature).

You can run the code snippet, for example, as part of a console application or within the initialization code of a custom module.

Important

You need to run the code BEFORE you enable content tree-based routing, i.e. the Routing mode setting needs to be set to Custom.

Manually storing former URLs



using System.Collections.Generic;

using CMS.DataEngine;
using CMS.DocumentEngine.Internal;

namespace CMS.DocumentEngine
{
    public class CustomUrlsBackup
    {
        /// <summary>
        /// This is an example code snippet that generates former URL paths for pages with a URL pattern.
        /// Former URLs are generated only for existing culture versions of pages.
        /// </summary>
        /// <param name="siteIdentifier">Site identifier (site code name or ID).</param>
        public void BackupUrls(SiteInfoIdentifier siteIdentifier)
        {
            var classesWithUrl = GetClassesWithUrl(siteIdentifier);

            foreach (var classWithUrl in classesWithUrl)
            {
                new DocumentQuery(classWithUrl)
                    .AllCultures()
                    .OnSite(siteIdentifier)
                    .ForEachPage(pagesInBatch => ProcessBatch(pagesInBatch, siteIdentifier), 100);
            }
        }

        // Loads all page types with a specified URL pattern and the 'URL' feature enabled
        private IList<string> GetClassesWithUrl(SiteInfoIdentifier siteIdentifier)
        {
            return DataClassInfoProvider.GetClasses()
                .Column("ClassName")
                .WhereNotEmpty("ClassURLPattern")
                .WhereTrue("ClassIsDocumentType")
                .WhereTrue("ClassHasURL")
                .OnSite(siteIdentifier)
                .GetListResult<string>();
        }

        // Saves the former URLs for a batch of pages
        private void ProcessBatch(DocumentQuery pagesInBatch, SiteInfoIdentifier siteIdentifier)
        {
            foreach (var page in pagesInBatch)
            {
                var formerUrl = CreateFormerUrlInfo(siteIdentifier, page);
                PageFormerUrlPathInfo.Provider.Set(formerUrl);
            }
        }

        // Creates a former URL for the specified page,
        // based on its current live site URL (resolved URL pattern)
        private PageFormerUrlPathInfo CreateFormerUrlInfo(int siteId, TreeNode page)
        {
            var urlPath = DocumentURLProvider.GetUrl(page);
            urlPath = PageUrlPathNormalizer.Normalize(urlPath.TrimStart('~')).Path;

            return new PageFormerUrlPathInfo
            {
                PageFormerUrlPathCulture = page.DocumentCulture,
                PageFormerUrlPathNodeID = page.NodeID,
                PageFormerUrlPathSiteID = siteId,
                PageFormerUrlPathUrlPath = urlPath                
            };
        }
    }
}