2

I have some components on my page that contain dynamic placeholders with other sublayouts placed inside them. Currently all of the datasource items get generated in the ./Local Components folder. My client is requesting that the datasource items get automatically nested so that for example if Sublayout B is inside Sublayout A, datasource item B will be created as a child of datasource item A. The dynamic placeholders are generated to all have a unique key determined by the rendering ID:

public class DynamicKeyPlaceholder : WebControl, IExpandable
{
    protected string _key = Placeholder.DefaultPlaceholderKey;
    protected string _dynamicKey = null;
    protected Placeholder _placeholder;

    public Placeholder InnerPlaceholder
    {
        get { return _placeholder; }
    }

    public string Key
    {
        get { return _key; }
        set { _key = value.ToLower(); }
    }

    protected string DynamicKey
    {
        get
        {
            if (_dynamicKey != null)
            {
                return _dynamicKey;
            }

            _dynamicKey = _key + "_" + RenderingContext.Current.Rendering.UniqueId;

            return _dynamicKey;
        }
    }

    protected override void CreateChildControls()
    {
        Sitecore.Diagnostics.Tracer.Debug("DynamicKeyPlaceholder: Adding dynamic placeholder with Key " + DynamicKey);
        _placeholder = new Placeholder();
        _placeholder.Key = this.DynamicKey;
        this.Controls.Add(_placeholder);
        _placeholder.Expand();
    }

    protected override void DoRender(HtmlTextWriter output)
    {
        base.RenderChildren(output);
    }

    #region IExpandable Members

    public void Expand()
    {
        this.EnsureChildControls();
    }

    #endregion
}

I already have some pipelines to determine the datasource location which happen during the getRenderingDatasource pipeline.Here is one of them:

    public void Process(GetRenderingDatasourceArgs args)
    {
        Assert.IsNotNull(args, "args");
        if (!args.RenderingItem["Datasource Location"].ToLower().Contains("[local]"))
        {
            //nothing to replace here, move along
            return;
        }

        Database database = Context.Database;
        if (database == null || string.IsNullOrEmpty(database.Name) || database.Name.ToLower().Equals("core"))
        {
            database = args.ContentDatabase;
            if (database == null)
            {
                return;
            }
        }
        else
        {
            return;
        }

        ListString str = new ListString(args.RenderingItem["Datasource Location"]);
        foreach (string str2 in str)
        {
            if (!str2.Trim().StartsWith("[local]", StringComparison.InvariantCultureIgnoreCase))
            {
                continue;
            }

            //Get the local components folder
            Item localComponentsFolder = GetOrCreateLocalComponentsFolder(database, args.ContextItemPath);

            string path = str2.ToLower().Replace("[local]", localComponentsFolder.Paths.FullPath);
            Item datasourceLocation = database.GetItem(path);
            args.DatasourceRoots.Insert(0, datasourceLocation);
        }
    }

Now, I'm trying to figure out how, during this process, I can determine the placeholder the current rendering is in. If I have the placeholder key I think I can figure out the parent item, but I can't figure out how two get the placeholder key. args.RenderingItem is the Rendering item itself in the Layouts folder, which doesn't give me the info I need, and I've examined the other properties on args and can't find anything about the placeholder key. Is this possible?

1

It doesn't look like you can access the placeholder in the getRenderingDatasource pipeline unfortunately.

There is an potential solution posted for this here from Ruud van Falier though:

https://stackoverflow.com/questions/26225480/sitecore-dynamic-data-source-locations?rq=1

  1. Create a processor for the getPlaceholderRenderings. The GetPlaceholderRenderingsArgs will provide you with a placeholder key.

  2. Store the key in a session variable or HttpContext.Items instead of session (as suggested by Matthew Dresser on the above post)

  3. Retrieve the key from the session in your getRenderingDatasource processor.

This is the code Ruud van Falier shared:

// Add to the getRenderingDatasource pipeline.
public class GetPlaceholderKey
{
    public void Process(GetPlaceholderRenderingsArgs args)
    {
        System.Web.HttpContext.Current.Session["Placeholder"] = args.PlaceholderKey;
    }
}

// Add to the getRenderingDatasource pipeline.
public class GetAllowedDatasources
{
    public void Process(GetRenderingDatasourceArgs args)
    {
        Debug.WriteLine(System.Web.HttpContext.Current.Session["Placeholder"]);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.