Home > C#, Sitecore 6 > Queries in Datasource location on Sitecore Layouts

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:.";

}

Categories: C#, Sitecore 6 Tags: ,
  1. herskind
    15/05/2012 at 10:18

    This looks very useful extension to the getRenderingDatasource pipeline!

  2. 08/06/2012 at 15:53

    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

  3. 20/06/2012 at 11:52

    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

  4. abc
    23/11/2012 at 14:50

    You might want to update your post as you’ve got /pre tags on the page and they don’t paste too well!

  5. Wesley
    15/02/2013 at 15:27

    Awesome post, thanks!

  6. Syed Ahsan
    01/06/2015 at 14:15

    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 ?

  1. 06/06/2014 at 21:35
  2. 29/10/2014 at 09:03
  3. 25/02/2015 at 00:51

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: