The accepted answer is correct in most scenarios. However, I have come across a unique one that it does not satisfy.
Disclaimer: Avoid anything other than ID
's for the datasource to save yourself a lot of headaches.
Workflow/Modular Content
Workflow bundling was added in version 8.2. This allows content authors to move dependent page content through a shared workflow without having to move each rendering/datasource individually. For example, if your page changes from Draft to Staged, any dependent datasource items will automatically be moved to Staged as well. This is all courtesy of the new setting:
<setting name="WebEdit.AffectWorkflowForDatasourceItems" value="true" patch:source="Sitecore.ExperienceEditor.config"/>
After sorting through some Sitecore plumbing the following command is ultimately executed:
<command name="webedit:workflowwithdatasourceitems" type="Sitecore.ExperienceEditor.WebEdit.Commands.WorkflowWithDatasourceItems, Sitecore.ExperienceEditor" />
This command does execute Item.Visualization.GetRenderings()
. This method runs the resolveRenderingDatasource
pipeline and should return your datasources properly. The problem is that the Sitecore.Context.Item
is null when executed from the webedit:workflowwithdatasourceitems
which means when it ultimately runs the resolveRenderingDatasource
pipeline- all of your queries will fail since you don't have a Context Item to reference.
Thankfully, the fix is quite simple. Patch the webedit:workflowwithdatasourceitems
command and wrap with a ContextItemSwitcher
:
using System;
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.ExperienceEditor.Utils;
using Sitecore.Workflows.Simple;
namespace Common.CustomSitecore.Commands
{
[Serializable]
public class WorkflowWithDatasourceItems : Sitecore.Shell.Framework.Commands.Workflow
{
[UsedImplicitly]
protected new void WorkflowCompleteCallback(WorkflowPipelineArgs args)
{
base.WorkflowCompleteCallback(args);
using (new ContextItemSwitcher(args.DataItem))
{
var definedDatasources = ItemUtility.GetItemsFromLayoutDefinedDatasources(args.DataItem, Context.Device, args.DataItem.Language);
definedDatasources.AddRange(ItemUtility.GetPersonalizationRulesItems(args.DataItem, Context.Device, args.DataItem.Language));
definedDatasources.AddRange(ItemUtility.GetTestItems(args.DataItem, Context.Device, args.DataItem.Language));
foreach (var filterSameItem in ItemUtility.FilterSameItems(definedDatasources))
{
if (filterSameItem.Access.CanWrite() && (!filterSameItem.Locking.IsLocked() || filterSameItem.Locking.HasLock()))
WorkflowUtility.ExecuteWorkflowCommandIfAvailable(filterSameItem, args.CommandItem, args.CommentFields);
}
}
}
}
}
Patch
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<commands>
<command name="webedit:workflowwithdatasourceitems" type="Sitecore.ExperienceEditor.WebEdit.Commands.WorkflowWithDatasourceItems, Sitecore.ExperienceEditor">
<patch:attribute name="type">Common.CustomSitecore.Commands.WorkflowWithDatasourceItems, Common</patch:attribute>
</command>
</commands>
</sitecore>
</configuration>
AGAIN: Avoid anything other than ID
's for the datasource to save yourself a lot of headaches.