<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by Maria Fel</title> <link>https://world.optimizely.com/blogs/maria-fel/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>EpiServer Commerce 10.x. Custom Routing. SEO-FRIENDLY URL WITH CUSTOM SEGMENT</title>            <link>https://world.optimizely.com/blogs/maria-fel/dates/2017/4/episerver-commerce-10-x--custom-routing--seo-friendly-url-with-custom-segment/</link>            <description>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;Based on&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;a href=&quot;http://jondjones.com/episerver-segments-explained-registering-custom-routes-in-episerver&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;http://jondjones.com/episerver-segments-explained-registering-custom-routes-in-episerver&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;a href=&quot;http://jondjones.com/episerver-7-routing-for-dummies&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;http://jondjones.com/episerver-7-routing-for-dummies&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;a href=&quot;/link/55fe410f4f65482cab72fb59d47c7561.aspx?documentId=cms/7/905519a1-ceae-2bfd-faa2-13e8a0d94eaa&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;http://world.episerver.com/documentation/class-library/?documentId=cms/7/905519a1-ceae-2bfd-faa2-13e8a0d94eaa&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;a href=&quot;http://fellow.aagaardrasmussen.dk/2016/05/15/extend-routing-in-episerver-commerce-to-support-custom-segments/&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;http://fellow.aagaardrasmussen.dk/2016/05/15/extend-routing-in-episerver-commerce-to-support-custom-segments/&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;So&amp;hellip;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;I will start with task description: &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Need to implement SEO - friendly url for EpiServer Commerce 10.x site. For example, we need to have target url : &lt;/span&gt;&lt;a href=&quot;http://www.domain/v-segment/variation-code&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;www.domain/v-segment/variation-code&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt; only for variations and &amp;nbsp;we would like to keep hierarchical url (&lt;/span&gt;&lt;a href=&quot;http://www.domain/v-segment/variation-code&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;www.domain/catalog/segment/product/&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;) structure for all other pages, content.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;What instruments do we have out of the EpiServer box?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;&lt;strong&gt;First&lt;/strong&gt;, we have &lt;/span&gt;HierarchicalCatalogPartialRouter &lt;span style=&quot;font-weight: 400;&quot;&gt;out of the box for e - Commerce that provides us hierarchical url structure for Commerce and EpiServer entities. It is almost what we want. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;&lt;strong&gt;Second&lt;/strong&gt;, we have paradigm IPartialRouter from EpiServer (&lt;/span&gt;&lt;a href=&quot;/link/55fe410f4f65482cab72fb59d47c7561.aspx?documentId=cms/7/905519a1-ceae-2bfd-faa2-13e8a0d94eaa&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;http://world.episerver.com/documentation/class-library/?documentId=cms/7/905519a1-ceae-2bfd-faa2-13e8a0d94eaa&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;). That is not really suitable for our case, we do not want to reimplement hierarchical structure from scratch.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;So, let&amp;rsquo;s start.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Let&amp;rsquo;s extend &lt;/span&gt;HierarchicalCatalogPartialRouter. &lt;span style=&quot;font-weight: 400;&quot;&gt;This way I took from &lt;/span&gt;&lt;a href=&quot;http://fellow.aagaardrasmussen.dk/2016/05/15/extend-routing-in-episerver-commerce-to-support-custom-segments/&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;http://fellow.aagaardrasmussen.dk/2016/05/15/extend-routing-in-episerver-commerce-to-support-custom-segments/&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;. I would like to add some important details to solve our task and extend it in the way to be able to work with static segments (&amp;ldquo;v-segment&amp;rdquo; in our case).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public class CustomHierarchicalCatalogRouter: HierarchicalCatalogPartialRouter {

    public const string CustomRouteSegment = &quot;v-segment&quot;;

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Right after we created new class and inherited it from &lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;HierarchicalCatalogPartialRouter&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;, we have to implement several c-tors, and we are able to override following methods:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;GetPartialVirtualPath&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt; It is used to provide URL specific structure outside. Like provide external url.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;RoutePartial&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;It is used to match current url segment to the CatalogEntity. Kind of opposite thing for &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;GetPartialVirtualPath&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;FindNextContentInSegmentPair&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;It is used to resolve CatalogEntity due to hierarchical url structure. Basically &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;base.RoutePartial&lt;/span&gt; &lt;span style=&quot;font-weight: 400;&quot;&gt;calls it recursively to navigate and resolve Entity. Right after &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;FindNextContentInSegmentPair &lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;call &lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;base.RoutePartial&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt; calls another method IsValid. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;strong&gt;IsValidRoutedContent(CatalogContentBase content)&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;This checks if resolved object is CatalogEntity.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;Mostly that is all our instruments.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;Let&amp;rsquo;s go.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public override PartialRouteData GetPartialVirtualPath(CatalogContentBase content, string language,RouteValueDictionary routeValues, RequestContext requestContext){

&amp;nbsp;&amp;nbsp;var variation = content as Variation;

&amp;nbsp;&amp;nbsp;if (variation == null)&amp;nbsp;return base.GetPartialVirtualPath(content, language, routeValues, requestContext);&amp;nbsp; &amp;nbsp;

&amp;nbsp;&amp;nbsp;

&amp;nbsp; return new PartialRouteData&amp;nbsp;{

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BasePathRoot = RouteStartingPoint,

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PartialVirtualPath = $&quot;{VariationRouteSegment}/{HttpUtility.UrlPathEncode(variation.RouteSegment)}&quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;Here we will provide our new URL structure outside only for Variation.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;Next, we have to provide support for our new URL structure for Variation. In other words be able to resolve incoming URL that contains our new segment and match it to CatalogEntity. Have a look at the code below.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: &#39;courier new&#39;, courier, monospace; font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400; color: #808080;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Important thing here is that we no need to override FindNextContentInSegmentPair, because Variation URL has no hierarchical structure (we manage that in &lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;segmentContext.RemainingPath = string.Empty;&lt;/span&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;). And we do not touch this hierarchical resolving mechanism for all other Catalog Entities. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;And the latest thing in this class is to forbid resolving Variation by old hierarchical rules. For now our resolver will perfectly resolve Variation if it comes in old way like this:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;&lt;a href=&quot;http://www.domain/catalog/segment/product/variation-code&quot;&gt;www.domain/catalog/segment/product/variation-code&lt;/a&gt;&lt;a href=&quot;http://www.domain/v-segment/variation-code&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;protected override bool IsValidRoutedContent(CatalogContentBase content)&amp;nbsp;&amp;nbsp;{

&amp;nbsp; &amp;nbsp; //To forbid hierarchical variation url structure:

&amp;nbsp; &amp;nbsp; &amp;nbsp;if (content is Variation)&amp;nbsp;return false;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;

&amp;nbsp; &amp;nbsp; &amp;nbsp;return base.IsValidRoutedContent(content);

&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;So, now we are done with Router customization. Let&amp;rsquo;s register it in&lt;strong&gt; Initialization module&lt;/strong&gt;.&lt;/span&gt;&lt;span style=&quot;font-weight: 400; color: #808080; font-size: 10pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;var hierarchicalCatalogRouter = new CustomHierarchicalCatalogRouter(commerceService, GetStartingPoint, GetCatalogRoot(contentRepository, referenceConverter), false);

&amp;nbsp; RouteTable.Routes.RegisterPartialRouter(hierarchicalCatalogRouter);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;Next thing that we have to take care of is Register our route.&lt;/span&gt;&lt;span style=&quot;font-weight: 400; color: #808080; font-size: 10pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;var segmentRouter = ServiceLocator.Current.GetInstance&amp;lt;IUrlSegmentRouter&amp;gt;();

&amp;nbsp; segmentRouter.RootResolver = sd =&amp;gt; sd.StartPage;

&amp;nbsp; var parameters = new MapContentRouteParameters {

&amp;nbsp; &amp;nbsp; UrlSegmentRouter = segmentRouter,

&amp;nbsp; &amp;nbsp; Direction = SupportedDirection.Incoming,

&amp;nbsp; &amp;nbsp; SegmentMappings =&amp;nbsp;new Dictionary&amp;lt;string, ISegment&amp;gt; {{&amp;ldquo;v-segment&amp;rdquo;, new &amp;nbsp;ParameterSegment(&amp;ldquo;&amp;rdquo;v-segment) &amp;nbsp;}}

&amp;nbsp; };

&amp;nbsp; RouteTable.Routes.MapContentRoute(

&amp;nbsp; &quot;variation_node&quot;,

&amp;nbsp; &quot;{language}/v-segment/{node}/{action}/&quot;,

&amp;nbsp; &amp;nbsp;new&amp;nbsp; &amp;nbsp;{

&amp;nbsp; &amp;nbsp; controller = &quot;Variation&quot;,

&amp;nbsp; &amp;nbsp; action = &quot;Index&quot;,

&amp;nbsp; &amp;nbsp;language = UrlParameter.Optional,

&amp;nbsp; &amp;nbsp;},

&amp;nbsp;&amp;nbsp;parameters);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 10pt;&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Important thing here is &amp;nbsp;- &lt;strong&gt;segment parameters&lt;/strong&gt;. We have to tell to Router that we are looking only for URL structure that definitely contains this particular segment &amp;ldquo;&lt;/span&gt;&lt;a href=&quot;http://www.domain/v-segment/variation-code&quot;&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;v-segment&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;&amp;rdquo;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;&lt;strong&gt;Note&lt;/strong&gt;: in current implementation we also know which controller will handle this URL.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-weight: 400; font-size: 10pt;&quot;&gt;That&amp;rsquo;s it!&lt;/span&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</description>            <guid>https://world.optimizely.com/blogs/maria-fel/dates/2017/4/episerver-commerce-10-x--custom-routing--seo-friendly-url-with-custom-segment/</guid>            <pubDate>Mon, 10 Apr 2017 22:15:35 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>