Create Friendly URLs for Catalog Items

Create URLs to content without using query strings.

Complete the following prerequisites:

At your visual studio solution setup:

  1. Create a new pipeline processor web.config file in /configuration/sitecore/pipelines/httpRequestBegin under the httpRequestBegin pipeline, inserted before the ItemResolver processor.
    This processor will find urls of a specific format and the associated item, then set Sitecore.Context.Item to that item.
    MVCSite.SitecorePipelines
    {
        using Sitecore;
        using Sitecore.Pipelines.HttpRequest;
     
        public class CatalogItemResolver
        {
            public override void Process(PipelineArgs args)
            {
                if (Context.Item == null)
                {
                    return;
                }
     
                // insert item resolver code here
            }
        }
    }
  2. Edit your patch config file.
    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
                <sitecore>
                            <pipelines>
                                        <httpRequestBegin>
                                                    <processor type="MVCSite.SitecorePipelines.CatalogItemResolver, MVCSite" patch:before= "processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" />
                                        </httpRequestBegin>
                            </pipelines>
                </sitecore>
    </configuration>
  3. Parse URLs with Routes.
    public virtual CatalogRouteData GetCatalogItemFromIncomingRequest()
    {
        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(System.Web.HttpContext.Current));
     
        if (routeData != null)
        {
            var data = this.GetRouteDataValue(routeData);
     
            return data;
        }
     
        return null;
    }
     
    public virtual CatalogRouteData GetRouteDataValue(RouteData routeData)
    {
        var data = new CatalogRouteData();
     
        if (routeData.Values.ContainsKey(ItemTypeField))
        {
            data.IsProduct = routeData.Values[ItemTypeField].ToString() == ProductItemType ? true : false;
        }
     
        if (routeData.Values.ContainsKey(IdField))
        {
            data.Id = routeData.Values[IdField].ToString();
        }
     
        if (routeData.Values.ContainsKey(CatalogField))
        {
            data.Catalog = routeData.Values[CatalogField].ToString();
        }
     
        if (string.IsNullOrEmpty(data.Catalog))
        {
            var defaultCatalogItem = Sitecore.Context.Database.GetItem(CommerceConstants.KnownItemIds.DefaultCatalog);
     
            if (defaultCatalogItem != null)
            {
                data.Catalog = defaultCatalogItem[CommerceConstants.KnownFieldIds.CatalogSettingValue];
            }
        }
     
        return data;
    }
  4. Retrieve the item using SearchNavigation.GetProduct or SearchNavigation.GetCategory
    Sitecore.Data.Items.Item foundItem = null;
    foundItem = SearchNavigation.GetProduct(routeData.Id, routeData.Catalog);
  5. Cache the mapping between the URL and the Sitecore item id.
    ICacheProvider cacheProvider = CommerceTypeLoader.GetCacheProvider(CommerceConstants.KnownCacheNames.FriendlyUrlsCache);
    var id = cacheProvider.GetData<ID>(CommerceConstants.KnownCachePrefixes.Sitecore, CommerceConstants.KnownCacheNames.FriendlyUrlsCache, cachekey);
    if (foundItem != null)
    {
        cacheProvider.AddData<ID>(CommerceConstants.KnownCachePrefixes.Sitecore, CommerceConstants.KnownCacheNames.FriendlyUrlsCache, cachekey, foundItem.ID);
    }
  6. Create a new link provider that will render links for catalog and product items in a specific form.
    1. Inherit from the Sitecore LinkProvider and call the base provider if the item is not a product or category
      public class MyLinkProvider : LinkProvider
    2. Check if an item is a product or category by using SearchHelpers.IsItemProduct or SearchHelpers.IsItemCategory
      var searchManager = CommerceTypeLoader.CreateInstance<ICommerceSearchManager>();
      if (searchManager.IsItemProduct(item))
      {
          // build and return Product link
      }
      else if (searchManager.IsItemCategory(item))
      {
          // build and return Category link
      }
  7. Register your link provider in your include file and set it as the new default link provider.
    /configuration/sitecore/linkManager
    <linkManager defaultProvider="sitecore">
          <patch:attribute name="defaultProvider">MyLinkProvider</patch:attribute>
          <providers>
            <add name="MyLinkProvider" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" type="MySite.SitecorePipelines.MyLinkProvider, MySite"/>
          </providers>
        </linkManager>