Kentico / xperience-by-kentico-kentico-migration-tool

A customizable tool that migrates older Kentico solutions to the latest version of Xperience by Kentico.
MIT License
5 stars 1 forks source link

Support migration of page type URL patterns #245

Open liamgold opened 1 week ago

liamgold commented 1 week ago

Motivation

In Kentico Xperience 13, you could create page types that had their own URL pattern rather than using content tree-based routing. This meant that URLs could be based off patterns instead of the content tree.

Although the KX13 documentation recommends content tree routing, some websites will have been built using custom routing with URL patterns. Especially if they have previously migrated from Kentico 12 MVC as content tree-based routing was not available at the time.

These existing clients should be able to use the migration toolkit, they should not be left out.

Proposed solution

As Xperience by Kentico does not support page type URL patterns, it obviously can't be mapped 1:1. I think a suitable solution would be to resolve the URL of the existing page, store it as a vanity URL when that is released, and set that URL as the canonical. This way, migrated pages will keep the existing URL and not break when switching to Xperience by Kentico.

The expectation then would be that new pages using these page types would start to use the content tree-based routing.

If the team managing the website wanted to continue using page type URL patterns, it would be their responsibility to implement a bespoke solution to handle this going forward.

liparova commented 1 week ago

Thank you for your recommendation. We'll evaluate its feasibility and provide regular updates on its integration progress.

Sapphirress commented 6 days ago

Hi Liam, technically this could be added into the migration tool, however we think that this is not a best practice for utilizing Vanity URLs and therefore we decided not to go on with the implementation. Instead, we will recommend to achieve this scenario through customization and offer an example for this purpose.

liamgold commented 6 days ago

That's fine with me - as long as there is a recommended approach to follow that supports these clients then I am happy.

If we're no longer using Vanity URLs for this, do you know how long it will take for the recommended approach to be published?

tkrch commented 2 days ago

Hi @liamgold, one option is to use dynamic route transformer. Simplistic sample for Dancing Goat project:

1) create class MyDynamicRouteTransformer as follows:

namespace DancingGoat;

using System;
using System.Linq;
using System.Threading.Tasks;
using CMS.ContentEngine.Internal;
using CMS.Core;
using CMS.DataEngine;
using CMS.Websites.Internal;
using CMS.Websites.Routing;
using Kentico.Content.Web.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;

public class MyDynamicRouteTransformer : DynamicRouteValueTransformer
{
    private readonly IWebPageDataContextInitializer _contextInitializer;
    private readonly IWebsiteChannelContext _websiteChannelContext;

    public MyDynamicRouteTransformer(IWebPageDataContextInitializer contextInitializer, IWebsiteChannelContext websiteChannelContext)
    {
        _contextInitializer = contextInitializer;
        _websiteChannelContext = websiteChannelContext;
    }

    public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext
        httpContext, RouteValueDictionary values)
    {
        return await Task.Run(async () =>
        {
            // TODO: retrieve web page You want to display
            var webPageItem = WebPageItemInfo.Provider.Get().WhereEquals(nameof(WebPageItemInfo.WebPageItemTreePath), "/Home").FirstOrDefault() 
                ?? throw new InvalidOperationException("Page not found!");

            // TODO: get language from route
            var contentLanguage = await Service.Resolve<IContentLanguageRetriever>().GetDefaultContentLanguage();
            // TODO: get contenttype of desired content item
            var contentItemInfo = ContentItemInfo.Provider.Get(webPageItem.WebPageItemContentItemID);
            var webPage = new RoutedWebPage
            {
                WebPageItemID = webPageItem.WebPageItemID,
                WebPageItemGUID = webPageItem.WebPageItemGUID,
                LanguageID = contentLanguage.ContentLanguageID,
                LanguageName = contentLanguage.ContentLanguageName,
                ContentTypeID = contentItemInfo.ContentItemContentTypeID,
                ContentTypeName = DataClassInfoProvider.GetClassName(contentItemInfo.ContentItemContentTypeID),
                WebsiteChannelID = _websiteChannelContext.WebsiteChannelID,
                WebsiteChannelName = _websiteChannelContext.WebsiteChannelName,    
            };

            // Initialize WebPageDataContext in order to get WebPageRetriever work
            _contextInitializer.Initialize(webPage);

            // TODO: select controller
            values["controller"] = "DancingGoatHome";
            // TODO: select controller action
            values["action"] = "Index";
            return values;
        });
    }
}

2) Register it in ServiceCollection: builder.Services.AddTransient<MyDynamicRouteTransformer>();

3) map transformer: `app.MapDynamicControllerRoute("/dynamic-route-test/{foo?}/{bar?}");``

4) open ./Controllers/DancingGoatHomeController.cs

change

public async Task<IActionResult> Index()

to

public async Task<IActionResult> Index([FromRoute] string foo, [FromRoute] string bar)

then put breakpoint into Index method

5) run project and open url: http://[domain]/dynamic-route-test/testvalue1/testvalue2

6) values populated: image continue and page should render correctly

let me know, if this helped

liamgold commented 1 day ago

Thanks @tkrch - this would only correct it from a routing perspective, right?

How do you suggest correcting the URL being displayed on the page in the web channel?

When resolving the page's URL through Kentico's APIs will the content-tree based URL still be used?

When a URL has been previously added to rich text blocks, and in the future, which URL will be used?

tkrch commented 1 day ago

@liamgold I'm currently testing alternative solution. I'll notify You when i confirm that it is feasible and implemented.