Wilin’ Out With Wildcards in Sitecore

What Are Wildcards

Sitecore’s URL Resolver uses the path of an Item to generate the URL. So if in sitecore we have an item:

sitecore/content/<siteHomeNode>/Blogs/My First Blog

The URL resolver will create the URL:

https://mywebsite/blogs/my-first-blog

Makes Sense, right? Right! Let’s take a look at another scenario: lets say we have a multi site instance that want to display the same blogs on both sites. We could use cloning, or copy the blogs from one site or another. We could even just create the pages in the tree of the site with renderings that then point to the blog we want to display on that page. Personally, I’m not a fan of those approaches because it puts a lot of burden on the content editors. 

The approach I like to take, and going to discuss in this blog is using wildcard pages, or dynamic URLS as they are sometimes called.
The idea behind it is pretty straight forward: lets go back to our original site:

https://mywebsite/blogs/my-first-blog

In sitecore it will look something like this”

sitecore/content/<siteHomeNode>/Blogs/

Where the node Blogs is going to a special node called a Wildcard. Every page after the Wildcard node will not actually exist in Sitecore, it will be dynamically loaded!

Before I continue, I am aware that wildcards are implemented in Sitecore, but sometimes I like to do things my way and this is one of those times! So feel free to continue reading or leave me a nasty comment.

Create a Wildcard Template

The first step is pretty straight forward: you want to create a page template. The page template isn’t anything special; it will have standard values where we will set presentation details add any standard components on it etc. We will eventually put a Dynamic Blog rendering that loads our blog content dynamically via URL, but that will come later.

Item Resolver

Since our dynamic pages don’t actually exist, if we navigate to https://mywebsite/blogs/my-first-blog we will get a 404 error. The item My First Blog doesn’t actually exist under Blogs (our wildcard). So we need to create a custom pipeline process that extends HttpRequestProcessor

 

C#
using System;
using Sitecore.Pipelines.HttpRequest;


namespace Techcrane.Foundation.Links
{
    public class DynamicBlogProcessor : HttpRequestProcessor
    {
        public override void Process(HttpRequestArgs args)
        {
            // continue processing if we have a direct hit on an item
            if (Sitecore.Context.Item != null)
            {
                return;
            }

            var currentUrl = args.HttpContext.Request.Url.LocalPath;
            var urlSegments = currentUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); // read from
            var wildcardPage = Sitecore.Context.Site.StartPath;
			
			// Loop throught url and try to see if the path contains our wildcard item
            foreach (var segment in urlSegments)
            {
                wildcardPage += $"/{segment}";
                var wildcardItem = Sitecore.Context.Database.GetItem(wildcardPage);

                if(wildcardItem != null && wildcardItem.TemplateName == "Wildcard Item")
                {
                    Sitecore.Context.Item = wildcardItem;
                    return;
                }
            }
        }
    }
}

This code first checks to see if the URL we are requesting is maps to an actual item in which case we just return. If the item does NOT exist we parse the URL until we get an item. Once we get an actual item back, we check to see if it is our wildcard item. If the item is the wildcard, we set the context to that wildcard item. This will make Sitecore think serve up the Wildcard page when we make a request to that URL. From there, the Dynamic Blog rendering takes over to display the actual blog content

Dynamic Blog Rendering

Up to this point we have created a wildcard page template and let the sitecore know how to handle our dynamic URL. Now we need to display the actual content to the page. First thing we need to do is find out what blog we are trying to display. To do this, we need to take the URL segment after https://mywebsite/blogs so my-first-blog and do a search against the index. This should return the actual blog item that we want to display so just display the fields. Done and Done!

You could stop there but your content editors will loose inline editing. Some might not mind, but from my experience some will and they will come looking for you. Luckily, this is actually not as bad as it seems. To do this you will want to get the rendering context, and set the rendering context item to your blog. Viola! you now have inline editing

C#
using Sitecore.Mvc.Presentation;
using Sitecore.XA.Foundation.Mvc.Controllers;
using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.Data.Items
using System.Web.Mvc; ;

namespace Echopark.Feature.Shop.Controllers
{
    public class DynamicRendering : StandardController
    {
        public ContentResult MyAction()
        {
            var url = Sitecore.Context.HttpContext.Request.Url.LocalPath;

            var wildcardPage = Sitecore.Context.Site.StartPath;
            var blogTitle = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(); // Assume the last part of the URL is the blog

            Item blogItem = FindBlog(blogTitle);

            if (blogItem != null)
            {
                RenderingContext renderingContext = RenderingContext.CurrentOrNull;
                Rendering currentRendering = renderingContext.Rendering;
                renderingContext.ContextItem = blogItem;
            }


            return new ContentResult();
        }
    }
}

ItemUrlBuilder

The final piece of the puzzle is how do you generate link to your blog items. Since the blog items don’t live under the blog node, we need to tell Sitecore how we want to build the URL to those items. On older versions of Sitecore you would use LInkProvider, but in Sitecore 10+ that is deprecated and we extend ItemUrlBuilder. We override the Build method to return the desired URL of the blog item. We can have something as simple as hardcoding the base URL and concatenating the string (don’t do this) to complex logic. Personally, I like to throw it into a setting in the tree. But it’s your site, do what you want!

C#
using Sitecore.Mvc.Presentation;
using Sitecore.XA.Foundation.Mvc.Controllers;
using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.Data.Items;
using System.Web.Mvc; 

namespace Echopark.Feature.Shop.Controllers
{
    public class DynamicRendering : StandardController
    {
        public ContentResult MyAction()
        {
            var url = Sitecore.Context.HttpContext.Request.Url.LocalPath;

            var wildcardPage = Sitecore.Context.Site.StartPath;
            var blogTitle = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(); // Assume the last part of the URL is the blog

            // Use search to find th eblog by Title 
            Item blogItem = FindBlog(blogTitle);

            if (blogItem != null)
            {
                RenderingContext renderingContext = RenderingContext.CurrentOrNull;
                Rendering currentRendering = renderingContext.Rendering;
                renderingContext.ContextItem = blogItem;
            }
            return new ContentResult();
        }
    }
}

There you have it, easy peasy! Give it a try and happy coding!

1 thought on “Wilin’ Out With Wildcards in Sitecore”

Leave a Comment