Autogenerated relative datasource location

An easy way to create autogenerated relative datasource location which increases the flexibility of your components and some tricks to workaround one issue.

A new component

At the beginning, we have to create a test component. I created a view rendering which uses "/sitecore/templates/Sample/Sample Item" as a data source template and "./Outer/Inner" as a data source location. Of course, the Outer and Inner folders don't exist... yet :).

New test component

New test component

Pro tip: We will use the getRenderingDatasource pipeline and in order to trigger the event our View Rendering has to access its data source. I simply added @Html.Sitecore().Field("Title") to the cshtml file.

<div>@Html.Sitecore().Field("Title")</div>

Rendering datasource pipeline

As mentioned, we gonna use getRenderingDatasource which defines the data source for our component. Our new processor has to be patched at the beginning of the pipeline because by default the first processor in the pipeline is GetDatasourceLocation.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>

    <pipelines>
      <getRenderingDatasource>
        <processor type="SitecoreKickOff.Pipelines.RelativeDataSource, SitecoreKickOff" patch:before="*[1]" />
      </getRenderingDatasource>
    </pipelines>

  </sitecore>
</configuration>

Now it's time for some C# code. For the sake of simplicity, I omitted most of "if" statements and guard clauses and I assumed that the data source location doesn't exist.

using Sitecore;
using Sitecore.Data;
using Sitecore.Pipelines.GetRenderingDatasource;
using Sitecore.SecurityModel;

namespace SitecoreKickOff.Pipelines
{
    public class RelativeDataSource
    {
        private static readonly TemplateID FolderTemplateId = new TemplateID(new ID("{A87A00B1-E6DB-45AB-8B54-636FEC3B5523}"));
  
        public void Process(GetRenderingDatasourceArgs args)
        {
            var dataSourceLocation = args.RenderingItem["Datasource Location"];
            var contextItem = args.ContentDatabase.GetItem(args.ContextItemPath);

            var folders = dataSourceLocation.Substring(2).Split('/');

            using (new SecurityDisabler())
            {
                foreach (var folder in folders)
                    contextItem = contextItem.Add(folder, FolderTemplateId);
            }
        }
    }
}

Most of the code is pretty straightforward, but this isn't finished. In the first paragraph, I mentioned about an issue. Basically, now when we add our new component on the page the data source folders are created properly but our component is not added to the page because the page is being refreshed.

The reason for this is that the WebEditRibbon is subscribed to the ItemCreated notification and refreshes the page if a new item is created during the request.

The first workaround is to wrap the contextItem.Add(folder, FolderTemplateId); statement into:

using (new SecurityDisabler())
{
    Client.Site.Notifications.Disabled = true;
    foreach (var folder in folders)
        contextItem = contextItem.Add(folder, FolderTemplateId);
    Client.Site.Notifications.Disabled = false;
}

The second solution is to use EventDisabler, however, you need to remember that when you're within EventDisabler context, "item:saved" event won't trigger.

using (new SecurityDisabler())
{
    using (new EventDisabler())
        foreach (var folder in folders)
            contextItem = contextItem.Add(folder, FolderTemplateId);
}

Playground

Now, choose your way 🙂 and let's test the code.

Creating a new data source

Creating a new data source

The relative datasource location has been created successfully.

Relative datasource location in Content Editor

Relative datasource location in Content Editor

I plan to develop this and extended to the point where I have not only automatically generated relative datasource location:). Hope, this was helpful and see you soon.


Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

meetup

SUGPL Meetup Warsaw – Video Presentation

Video presentation SUGPL Meetup Warsaw – 23 March 2018 In my last post, I have invited you all to a SUGPL Meetup Warsaw which took place on 23 March 2018. I have been one of the presenters. Read more…

meetup

SUGPL Meetup Warsaw – 23 March 2018

SUGPL Meetup Warsaw This gonna be a short post but I would like to invite you all to a SUGPL Meetup Warsaw which takes place on 23 March 2018. I will be there and I will Read more…

sitecore

Customize Rich Text Editor in Sitecore

Recently, I have come up with an idea to Customize Rich Text Editor in Sitecore by adding a button that embeds GIPHY player into my content. So, I thought that I will share this with Read more…