My previous blog posts about multiple catalogs in multiple sites setting here and here has helped one customer (hopefully more) to address their problem. They tried the approach and it works for them. Now they came back and ask if they can remove the catalog name from the URL entirely. Is that something that can be done. Fortunately, yes.
Before moving on, let’s be clear: this is obviously custom development and is not officially supported by Episerver. I.e. it’s neither tested and documented. Normally you would have to go to Expert Services for such requirement. For this blog, I provide those samples for free (you don’t even have to buy my book 😉 ), but remember I can only do that much. You have to test to see if it works for you (I of course do the basic testing), and if you run into problems later, I might not be able/available to help.
Now get back to the problem. Previously the router looks like this
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); }
And it works great with http://commerceref/en/fashion/mens/mens-shoes/p-36127195/ or http://commerceref/en/products/mens/mens-shoes/p-36127195/. But now they want to completely remove the catalog name from the url. They can’t make it works with http://commerceref/en/mens/mens-shoes/p-36127195/.
Why? Because the router is returning the catalog for /mens/
segment. In next segment (mens-shoes
), we fallback to the default implementation, which can’t find any matching content as children of that definedCatalogContent
.
The solution: Because we want the first-level category to appear as direct child of the catalog root, we would have to return it ourselves. Instead of returning the catalog, we return the first node that matches /mens/
segment.
protected override CatalogContentBase FindNextContentInSegmentPair(CatalogContentBase catalogContent, SegmentPair segmentPair, SegmentContext segmentContext, CultureInfo cultureInfo) { if (catalogContent.ContentType == CatalogContentType.Root) { CatalogContent definedCatalogContent; var definedCatalogLink = _contentLoader.Get<StartPage>(RouteStartingPoint).CatalogLink; if (_contentLoader.TryGet<CatalogContent>(definedCatalogLink, cultureInfo, out definedCatalogContent)) { var nodes = _contentLoader.GetChildren<NodeContent>(definedCatalogLink); return nodes.FirstOrDefault(n => n.RouteSegment.Equals(segmentPair.Next, StringComparison.OrdinalIgnoreCase)); } return null; } return base.FindNextContentInSegmentPair(catalogContent, segmentPair, segmentContext, cultureInfo); }
And it just works:
Now that’s just one part of the solution. We still need to make sure outgoing URLs respect that. I’ll leave that to you, as practice.