World is now on Opti ID! Learn more

sanjay.kumar
Jun 21, 2024
  63
(1 votes)

Remove a segment from the URL in CMS 12

Problem: I have created thousands of pages dynamically using schedule jobs with different templates (e.g. one column, two columns, etc..) and stored them under one of the specific container page templates but some of the page’s URLs were renamed.

So, I have two problems:

  1. How to ignore the container page name segment from the URL,
  2. Redirect to the new page without using any Add-ons or mapping the old one to the new URL.

Page Hierarchy

Name in URL

New URL (simple address url)

Expected result

Start Page -> Container Page -> One col page

study

students/study

- Remove the ‘container-page’ segment from URL.

- Apply 301 redirection for New URLs without adding any Add-Ons

https://local.alloy.com/container-page/study

 https://local.alloy.com/students/study

https://local.alloy.com/study

https://local.alloy.com/students/study

Solution: To fix the above problem we need to add the simple address for new URLs in each page and implement custom 301 redirections.

Register middleware into startup.cs file to bypass the container page segment from the URL

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IConfiguration configuration)
 {
      app.UseMiddleware<SkipContainerPageMiddleware>();
 }

Create the container page middleware to read the simple address and apply 301 redirection:

public class SkipContainerPageMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ISettingsService _settingsService;
    private readonly IContentLoader _contentLoader;

    public SkipContainerPageMiddleware(RequestDelegate next, ISettingsService settingsService, IContentLoader contentLoader)
    {
        _next = next;
        _settingsService = settingsService;
        _contentLoader = contentLoader;
    }

    public async Task Invoke(HttpContext context)
    {
       //Create a content reference type property in GlobalPageSettings or HomePage to read the container page location where all pages created
        var folderLocation = _settingsService.GetSiteSettings<GlobalPageSettings>()?.OEmbedFolderLocation ?? ContentReference.EmptyReference; 
        var folderName = "/" + _contentLoader.Get<IContent>(folderLocation).Name;

        if (context.Request.Path.StartsWithSegments(folderName, StringComparison.OrdinalIgnoreCase))
        {
            context.Request.Path = context.Request.Path.HasValue
                ? context?.Request?.Path.Value.Substring(folderName.Length)
                : string.Empty;

            if (context != null)
            {
                var url = GetSimpleAddress(folderName, context);
                if (url != null)
                {
                    var newURl = $"{context.Request.Scheme}://{context.Request.Host}/{url.Trim('/')}";
                    context.Response.Redirect(newURl, true);
                    return;
                }
            }
        }

        if (context != null)
            await _next(context);
    }

    private string? GetSimpleAddress(string parentSegment, HttpContext context)
    {
        var parentPage = _contentLoader
            .GetChildren<ContainerPage>(ContentReference.StartPage)
            .FirstOrDefault(x => string.Equals(parentSegment.Trim('/'), x.URLSegment, StringComparison.InvariantCultureIgnoreCase))?
            .ContentLink
            ?? ContentReference.EmptyReference;

        var url = context.Request.Path.HasValue ? context?.Request.Path.Value.Trim('/') : string.Empty;
        if (string.IsNullOrWhiteSpace(url) || parentPage == ContentReference.EmptyReference)
            return default;

        PageData? page = null;
        foreach (var item in url.Split('/'))
        {
            page = RecursivePageBySegment(parentPage, item);
            if (page != null)
                parentPage = page.ContentLink;
        }

        return page?.ExternalURL ?? url;
    }

    private PageData? RecursivePageBySegment(ContentReference parentPage, string urlSegment)
    {
        var children = _contentLoader.GetChildren<PageData>(parentPage);
        if (children.Count() == 0)
        {
            return _contentLoader.Get<PageData>(parentPage);
        }

        var page = children.FirstOrDefault(page => page.URLSegment.Equals(urlSegment, StringComparison.OrdinalIgnoreCase));
        return page ?? default;
    }
}

I hope this blog helps you achieve similar type functionality!

 

Jun 21, 2024

Comments

Please login to comment.
Latest blogs
Make Global Assets Site- and Language-Aware at Indexing Time

I had a support case the other day with a question around search on global assets on a multisite. This is the result of that investigation. This co...

dada | Jun 26, 2025

The remote server returned an error: (400) Bad Request – when configuring Azure Storage for an older Optimizely CMS site

How to fix a strange issue that occurred when I moved editor-uploaded files for some old Optimizely CMS 11 solutions to Azure Storage.

Tomas Hensrud Gulla | Jun 26, 2025 |

Enable Opal AI for your Optimizely products

Learn how to enable Opal AI, and meet your infinite workforce.

Tomas Hensrud Gulla | Jun 25, 2025 |

Deploying to Optimizely Frontend Hosting: A Practical Guide

Optimizely Frontend Hosting is a cloud-based solution for deploying headless frontend applications - currently supporting only Next.js projects. It...

Szymon Uryga | Jun 25, 2025

World on Opti ID

We're excited to announce that world.optimizely.com is now integrated with Opti ID! What does this mean for you? New Users:  You can now log in wit...

Patrick Lam | Jun 22, 2025

Avoid Scandinavian Letters in File Names in Optimizely CMS

Discover how Scandinavian letters in file names can break media in Optimizely CMS—and learn a simple code fix to automatically sanitize uploads for...

Henning Sjørbotten | Jun 19, 2025 |