Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
Experience Sitecore! | Wildcard items ("*"-pages) with MVC, passing the correct datasources based on requested item URL

Experience Sitecore!

Martin Miles on Sitecore

Wildcard items ("*"-pages) with MVC, passing the correct datasources based on requested item URL

As you probably know, there is a feature in Sitecore, called "wildcard items". Let's say you have a folder where multiple subitems suppose to be and should be presented by similar pages. Sitecore allows you create a wildcard item named "*" (asterisk) so that it will serve any request to this folder. Let's take a look on example below:


 Here we see clear separation of pages and data. Airports page has the only child - wildcard page item that is highlighted (and  you see its details). Below, in /Data folder, there is a corresponding data sources for each of the airport.

In usual scenario, there should be a page item created for each of airports from /data folder, and page's presentation details screen should have that data items set as the datasource for corresponding rendering (yes, we are on MVC here). But how to have this working, if we have only one universal page item? We have a rendering called Airport to display airport info, but how should we specify the datasource to it? 


The rendering relies on RenderingContext.Current.Rendering.DataSource as usual. And instead of datasource of specific airport, we get "*" item as the datasource in all cases, regardless of what airport's page we're loading.

I wanted to leave page's datasource and rendering untouched, as normal implementation. Instead, I decided to incline into mvc.getRenderer pipeline and resolve datasources for "*"-wildcard-items dynamically, based on the URL requested, so that rendering get corresponding data item from RenderingContext.Current.Rendering.DataSource. And of course, as "*"-items serves all possible requests to its folder, I must provide datasources only for matching data items, redirecting all the rest to 404 error page (since there's no data for the page - there's no sense in such a page). 

So here's my implementation of wildcard datasource resolver:



  
    
      
        
          Airport
        
      
    
  

Code referenced from configuration patch file:

    public class WildcardDatasource : GetRendererProcessor
    {
        public string RenderingName { get; set; }

        public override void Process(GetRendererArgs args)
        {
            if (args.PageContext.Item.Name == "*" && args.Rendering.RenderingItem.Name.IsSameAs(RenderingName))
            {
                string datasourceFolder = args.Rendering.DataSource.IsOK()
                    ? args.Rendering.DataSource
                    : string.Format("{0}/{1}", Paths.DataFolder.TrimEnd('/'), args.PageContext.Item.Parent.Name);

                string dataSourcePath = string.Format("{0}/{1}", datasourceFolder, 
                    args.PageContext.RequestContext.HttpContext.Request.Url.Segments.Last());

                var dataSourceItem = Sitecore.Context.Database.GetItem(dataSourcePath);
                if (dataSourceItem != null)
                {
                    args.Rendering.DataSource = dataSourcePath;
                }
                else
                {
                    // process 404 page not found
                }
            }
        }
    }


Things to improve in future: 

  1. Add support for nested wildcards
  2. Find the way wildcard items work with Page Editor
blog comments powered by Disqus