Multiple catalogs with same url

This is an excerpt from my second book . The first chapter is available to read for free.

A business is having an Episerver Commerce instance with multiple sites and multiple catalogs set up. They want to make sure each site will use one catalog, and all of them will share the same url for catalog structure. So it’ll be “https://site-a.com/products/category/”, and “https://site-b.com/products/category/”. Site A and site B are using different catalogs.

Is this doable? Yes! It’s just a matter of magic with the routing. This time, we would need to do an implementation of HierarchicalCatalogPartialRouter ourselves. First, let’s create a template for it:

    
public class MultipleSiteCatalogPartialRouter : HierarchicalCatalogPartialRouter
    {
        private readonly IContentLoader _contentLoader;

        public MultipleSiteCatalogPartialRouter(Func routeStartingPoint, CatalogContentBase commerceRoot, bool enableOutgoingSeoUri, IContentLoader contentLoader) 
            : base(routeStartingPoint, commerceRoot, enableOutgoingSeoUri)
        {
            _contentLoader = contentLoader;
        }
    }

We need to make sure each site uses the catalog it’s assigned for by overriding HierarchicalCatalogPartialRouter. When the router works on the url, it will start with from the left most segment, and figure out which content maps to that segment. We need to override that to set the catalog we want to use.

    
protected override CatalogContentBase FindNextContentInSegmentPair(CatalogContentBase catalogContent, SegmentPair segmentPair,
        SegmentContext segmentContext, CultureInfo cultureInfo)
    {
        if (catalogContent.ContentType == CatalogContentType.Root)
        {
            CatalogContent definedCatalogContent;
            var definedCatalogLink = _contentLoader.Get(RouteStartingPoint).CatalogLink;
            if (_contentLoader.TryGet(definedCatalogLink, cultureInfo, out definedCatalogContent))
            {
                return definedCatalogContent;
            }
        }
        return base.FindNextContentInSegmentPair(catalogContent, segmentPair, segmentContext, cultureInfo);
    }

 This will come with a side effect is that your catalog part in your url no longer matters. It can be “https://commercerecipes/en/abc/womens/”
or “https://commercerecipes/en/fashion/womens/” and the router can still figure it out, like magic. You might or might not want this side effect, so you can check if the segment matches an expected, defined value (we will discuss next), and return null if it does not match.

There are several way to decide which catalog to use, but because here we want it to attach to a site, we will get it from the start (aka Home) page. Just add a property to the start page

[AllowedTypes(typeof(CatalogContent))]
[UIHint(UIHint.CatalogContent)]
[Required]
public virtual ContentReference CatalogLink { get; set; }

This would render to a nice selector which is required and only allows catalogs:

Only catalogs are allowed

Because it’s possible that an editor will forget to set a linked catalog in the start page, we need don’t want the site to blow up, so we will just fallback to the default router.

This also explains why StartingPoint needs to be a Func<ContentReference> instead of just a ContentReference – Episerver needs to support multiple sites scenarios. If StartingPoint just takes a ContentReference, it will be a static start page for that instance. By taking Func<ContentReference> we can get the start page from the context, which is what we are going to do.

But that’s not yet enough. We make sure each site will use a different catalog for routing. That’s good, but we still all the catalogs to appear the same in the URL. With above implementation, we handled the incoming URL, but not yet outgoing URL. That would be the next recipe.

One thought on “Multiple catalogs with same url

Leave a Reply

Your email address will not be published. Required fields are marked *