Create Friendly URLs for Catalog Items
Create URLs to content without using query strings.
Complete the following prerequisites:
There are one or more virtual or base catalogs containing product and category definitions.
At your Visual Studio solution setup:
Create a new pipeline processor
web.config
file in/configuration/sitecore/pipelines/httpRequestBegin
under thehttpRequestBegin
pipeline, inserted before theItemResolver
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 } } }
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>
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; }
Retrieve the item using
SearchNavigation.GetProduct
orSearchNavigation.GetCategory
Sitecore.Data.Items.Item foundItem = null; foundItem = SearchNavigation.GetProduct(routeData.Id, routeData.Catalog);
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); }
Create a new link provider that will render links for catalog and product items in a specific form.
Inherit from the Sitecore LinkProvider and call the base provider if the item is not a product or category
public class MyLinkProvider : LinkProvider
Check if an item is a product or category by using
SearchHelpers.IsItemProduct
orSearchHelpers.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 }
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>