Will share the alternative implementation of Wildcards module of Adam Conn’s original idea.

The problem is that when it comes to Sitecore 7 or later this module appears not to be working out of the box due to changed Sitecore Rules Engine. And to be honest, working with rules may be a bit confusing and I found it hard to debug.

However there is still a way to fix the original module https://github.com/madoibito/revised-sitecore-wildcard-module-for-sitecore7.1orlater/wiki/How-to-change-wildcard-module-items-for-Sitecore-7.1-or-later-step-by-step for Sitecore 7+, but I needed some more flexibility.

So decided to implement something alternative.
So the task is as before – supporting data-driven URLs via Sitecore Wildcard (*) items.
All source code can be found here: https://github.com/vhil/helpfulcore-wildcards
The packed Sitecore module is in the same repository in its root.

Feature overview:

  • Not using Rules Engine anymore
  • Built in page item resolving and URL generation
  • Separate configuration for Item Resolving using ContentSearch API
  • Separate configuration for item URL generation
  • Single place for configuring the wildcards route
  • Fully configurable, extendable, easy to be changed and debuged.

I am going to play around with my ‘Fortis Demo’ solution and all project-relalted code and items can be found here: https://github.com/vhil/fortis-demo
So lets imagine,  I want to implement a product page in my solution, but will keep all my products in the item bucket outside of the website tree.
I have created a new page type template ‘Product Page’ which contains few fields and made it bucketable:

  • Product ID
  • Content Title
  • Content Image
  • Content Body

And created an item bucket under the shared content folder outside the website tree:
products-bucket
And on the site I want to show my products under /products item and my url for example has to be like this:

http://fortis.demo/products/[product-id]/[product-item-name]

So I created item tree under the website with wildcards in their names

/sitecore/content/Sites/fortis-demo/products/*/*

products-wildcard-item
Ok. Now I will implement a rendering that will list me my products on the product overview page

/sitecore/content/Sites/fortis-demo/products.

products-overview

Currently my rendering generated product detail URLs which contain bucket item paths:

http://fortis.demo/sitecore/content/shared-content/products-repository/2016/02/21/20/03/product-a
http://fortis.demo/sitecore/content/shared-content/products-repository/2016/02/21/20/11/product-b

But I want my urls to match the format mentioned above.
So I install a “Helpfulcore Wildcards Module-1.0.0” module.
All I need to do now is to register and configure a ‘wildcard route’ for my project page. I go to /sitecore/system/Modules/Wildcards/Routes item and create a new ‘Wildcard Route’ item under it.
wildcard-route
‘Wildcard Route’ template has fields for two main sections which reflect the module behavior:

  • Url Generation
  • Item Resolving

Url Generation:

url-generation

  • Wildcard Items – here I am referencing my endpoint wildcard item (in my case /sitecore/content/Sites/fortis-demo/products/*/*). Note that this is a TreelistEx field – this is done for multisite support. In case of multiple sites on your sitecore instance  just add all wildcard items from each site here and the module will resolve the most suitable one while url generation.
  • Url Generation Rules – this is a ‘Name Value List’ field and here we configure which wildcard should be replaces with which value related to the item.

For this field I have implemented a custom item reader which accepts its own syntax. It is actually pretty simple:

  • Prefix your fields with ‘@’. For example: @__Display Name
  • Prefix your properties with ‘@@. For example: @@Name
  • Use ‘.’ delimiter for creating a chain

Examples

  • @@Name
  • @__Display Name
  • @@Paths.@@Path
  • @@Parent.@@Name
  • @Custom Link Field.@@Name
  • @@Template.@@InnerItem.@__Standard values.@@Paths.@@Path

Notes:

  • Property names ARE case sensitive
  • Field names are NOT case sensitive

So in my case I set two values for each wildcard item:

{0, @Product ID}
{1, @@Name}

Which means

  • the wildcard at position [0] will be replaced with ‘Product ID’ field value of the item
  • the wildcard at position [1] will be replaced with ‘Name’ property value of the sitecore Item class.

In order to help to debug this syntax I have created an admin page which you can access by clicking on the ‘Url Generation Rules’ field title. It will lead you to /sitecore/admin/wildcardtokenextractor.aspx?sc_site=website page.

wildcard-tokenextractor

Here you can type the path or ID of testing item and write your query for concrete wildcard replacement. And then when you are sure your query gives correct result, just copy it into the field.

Item resolving:

I am hooking into the presentation layer and not the Item Resolving process by adding the processor into the <mvc.getPageItem> pipeline.

<pipelines>
      <mvc.getPageItem>
        <processor type="Helpfulcore.Wildcards.Pipelines.Response.GetPageItem.GetFromWildcard, Helpfulcore.Wildcards"
                   patch:after="processor[@type='Sitecore.Mvc.Pipelines.Response.GetPageItem.GetFromOldContext, Sitecore.Mvc']" />
      </mvc.getPageItem>
    </pipelines>

The item resolving is being implemented using the content search API and there is few more fields in the ‘Wildcard Route’ template for Item Resolving:

item-resolving

  • Item Search Root Node – specify here the root item of your item repository so the content search looks into items only inside of this item.
  • Item Templates – specify templates that the content search should filter by
  • Item Resolving Rules – and here in the same manner specify field for each wildcard. But now each value should represent the content search index field name. Note that not all wildcards are required to be participating in the item resolving, you can simply skip some of them and leave required ones only.

in my case that will be:

{0, product_id}
{1, _name}

Thats it!
Now if I refresh the product overview page I will see next urls being generated for my product items:

  • http://fortis.demo/products/pid-12345/product-a
  • http://fortis.demo/products/pid-65432/product-b

And when I click them I can see all the content taken from the resolved page item.

Configuration

The module installs an include config file /App_Config/Include/Helpfulcore/Helpfulcore.Wildcards.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="WildcardWrapSearchTermsInEncodedQuotes" value="false" />
      <setting name="WildcardTokenizedString" value=",-w-," />
      <setting name="WildcardProvider.RoutesPath" value="/sitecore/system/modules/wildcards/routes" />
    </settings>
	<wildcardManager defaultProvider="wildcardResolver">
      <providers>
        <add name="wildcardResolver" type="Helpfulcore.Wildcards.WildcardRouteResolver, Helpfulcore.Wildcards" />
      </providers>
    </wildcardManager>
	<wildcardItemResolver defaultProvider="contentSearch">
      <providers>
        <add name="contentSearch" type="Helpfulcore.Wildcards.ItemResolving.ContentSearchWildcardItemResolver, Helpfulcore.Wildcards" />
      </providers>
    </wildcardItemResolver>
    <urlGenerationTokenValueExtractor defaultProvider="itemReader">
      <providers>
        <add name="itemReader" type="Helpfulcore.Wildcards.UrlGeneration.TokenValueExtraction.ItemReaderTokenValueExtractor, Helpfulcore.Wildcards" />
      </providers>
    </urlGenerationTokenValueExtractor>
    <pipelines>
      <mvc.getPageItem>
        <processor type="Helpfulcore.Wildcards.Pipelines.Response.GetPageItem.GetFromWildcard, Helpfulcore.Wildcards"
                   patch:after="processor[@type='Sitecore.Mvc.Pipelines.Response.GetPageItem.GetFromOldContext, Sitecore.Mvc']" />
      </mvc.getPageItem>
    </pipelines>
    <linkManager defaultProvider="sitecore">
      <providers>
        <add name="sitecore">
          <patch:attribute name="type">Helpfulcore.Wildcards.UrlGeneration.WildcardLinkProvider, Helpfulcore.Wildcards</patch:attribute>
        </add>
      </providers>
    </linkManager>
    <events>
      <event name="publish:end">
        <handler type="Helpfulcore.Wildcards.Events.PublishEnd.WildcardsCachePurgeProcessor, Helpfulcore.Wildcards" method="ClearCache" />
      </event>
      <event name="publish:end:remote">
        <handler type="Helpfulcore.Wildcards.Events.PublishEnd.WildcardsCachePurgeProcessor, Helpfulcore.Wildcards" method="ClearCache" />
      </event>
    </events>
  </sitecore>
</configuration>

As you can see I have moved to the configuration pretty much everything. And in every class I implemented I tried to write virtual methods and members only so you can override whatever you want if you need some customization.
Also feel free to fork the repo and suggest a fix or improvement.

Module Contents:

Files:

  • /App_Config/Include/Helpfulcore/Helpfulcore.Wildcards.config
  • /sitecore/admin/WildcardTokenExtractor.aspx
  • /bin/Helpfulcore.Wildcards.dll

Items:

  • /sitecore/templates/Wildcards/Wildcard Route
  • /sitecore/system/Modules/Wildcards/Routes

Hope this will be helpful 🙂

Share article
See also

MVC renderings with xWrap framework – Sitecore Experience Wrapper

Read more Volodymyr Hil 10.12.2018

Introducing xWrap framework – Sitecore Experience Wrapper

Read more Volodymyr Hil 09.12.2018

A recap from Sitecore Symposium 2018 and MVP summit

Read more Volodymyr Hil 25.10.2018

Using the service bus to transfer messages between instance roles

Read more Volodymyr Hil 10.06.2018

Using Swagger in Sitecore solution as a helix feature

Read more Volodymyr Hil 19.02.2018