Queries in Datasource location on Sitecore Layouts
The datasource location specified on layouts is limited to Sitecore paths.
But working with multisite solutions it is sometimes necessary to have some items stored locally under Site.
This could be done fairly easy hooking in to the Sitecore pipeline “getRenderingDatasource”, found in the web.config under
“/configuration/sitecore/pipelines/getRenderingDatasource”
Below I’ve inserted my own
“PT.Framework.Pipelines.GetDatasourceLocation,PT.Framework.Pipelines”
<getRenderingDatasource> <processor type="Sitecore.Pipelines.GetRenderingDatasource.GetDatasourceLocation, Sitecore.Kernel" /> <processor type="PT.Framework.Pipelines.GetDatasourceLocation,PT.Framework.Pipelines" /> <processor type="Sitecore.Pipelines.GetRenderingDatasource.SetFallbackDatasourceLocations, Sitecore.Kernel" /> <processor type="Sitecore.Pipelines.GetRenderingDatasource.GetDatasourceTemplate, Sitecore.Kernel" /> <processor type="Sitecore.Pipelines.GetRenderingDatasource.GetTemplatesForSelection, Sitecore.Kernel" /> <processor type="Sitecore.Pipelines.GetRenderingDatasource.CheckDialogState, Sitecore.Kernel" /> <processor type="Sitecore.Pipelines.GetRenderingDatasource.GetDialogUrl, Sitecore.Kernel" /> </getRenderingDatasource>
The code for this step is really simple:
</pre> public void Process(GetRenderingDatasourceArgs args) { Assert.IsNotNull(args, "args"); DatasourceLocation = args.RenderingItem["Datasource Location"]; if(QueryInDataSourceLocation()) ProcessQuery(args); } private void ProcessQuery(GetRenderingDatasourceArgs args) { ContextItemPath = args.ContextItemPath; ContentDataBase = args.ContentDatabase; Item datasourceLocation = ResolveDatasourceRootFromQuery(); if (datasourceLocation != null) args.DatasourceRoots.Add(datasourceLocation); } private bool QueryInDataSourceLocation() { return DatasourceLocation.StartsWith(_query); } private Item ResolveDatasourceRootFromQuery() { string query = DatasourceLocation.Replace(_query, ContextItemPath); return ContentDataBase.SelectSingleItem(query); } private string DatasourceLocation { get; set; } private string ContextItemPath { get; set; } private Database ContentDataBase { get; set; } private const string _query = "query:."; <pre>
Now you can write queries like “./ancestor-or-self::*[@@templatekey=’site’]/Spots”
Update – Multiple datasource locations
Since one might want to have multiple Datasource Roots i made a change to the code so you can separate queries with the “|” delimiter. Note the normal sitecore path is still working and handled by the
“Sitecore.Pipelines.GetRenderingDatasource.GetDatasourceLocation”.
Now you can write
query:./ancestor-or-self::*[@@templatekey=’main section’]/QueryGlobal|/sitecore/content/GlobalSpots|query:./ancestor-or-self::*[@@templatekey=’site’]/Spots
public class GetDatasourceLocation { public void Process(GetRenderingDatasourceArgs args) { Assert.IsNotNull(args, "args"); DatasourceLocation = args.RenderingItem["Datasource Location"]; ContextItemPath = args.ContextItemPath; ContentDataBase = args.ContentDatabase; DatasourceRoots = args.DatasourceRoots; if(QueryInDataSourceLocation()) ProcessQuerys(args); } private void ProcessQuerys(GetRenderingDatasourceArgs args) { ListString possibleQueries = new ListString(DatasourceLocation); foreach (string possibleQuery in possibleQueries) { if (possibleQuery.StartsWith(_query)) ProcessQuery(possibleQuery); } } private bool QueryInDataSourceLocation() { return DatasourceLocation.Contains(_query); } private void ProcessQuery(string query) { Item datasourceLocation = ResolveDatasourceRootFromQuery(query); if (datasourceLocation != null) DatasourceRoots.Add(datasourceLocation); } private Item ResolveDatasourceRootFromQuery(string query) { string queryPath = query.Replace(_query, ContextItemPath); return ContentDataBase.SelectSingleItem(queryPath); } private string DatasourceLocation { get; set; } private string ContextItemPath { get; set; } private Database ContentDataBase { get; set; } private List<Item> DatasourceRoots { get; set; } private const string _query = "query:."; }
This looks very useful extension to the getRenderingDatasource pipeline!
Excellent post, I have this exact issue at the moment on a multi-site solution, expecting content authors to navigate the entire tree every time would not be acceptable
Hi there,
I’m currently doing some research for dynamic Datasource Locations for sublayouts. This is an excellent blogpost which really contributes to Nick Wesselman’s approach of using relative paths as the Datasource Location and creating dynamically folders on the datasource location.
I am going to combine these approaches.
Thanks!
gr,
Robbert Hock
Sitecore MVP
You might want to update your post as you’ve got /pre tags on the page and they don’t paste too well!
You are right.
Awesome post, thanks!
Hi @istern,
Thanks for really helpfull blogpost, but it does not work with Sitecore 7.2 initial release (rev. 140228). i know that it could be resolved by upgrading to at least 7.2 Update-2. but client is not agree to upgrade latest revision of 7.2.
so do you have any other approach or useful hint for this ?