2

I have a list of "modules" that I want to load depending on what template the current item is based on. This selection needs to be overridable. So I created a module loader component that has a datasource pointing to a folder that contains these modules. I iterate through the children of the folder, pull the RenderingReference and generate a new rendering. Finally I call the mvc.renderRendering pipeline. This seems to work great, but it does limit me some. The Parameters = ... line doesn't pull the parameters from the RenderingContext as this is a generic reference to the rendering and not the item's rendering properties.

So my question is, is there a better way to accomplish my overall goal here of loading dynamic items? Or can I get the parameters from my items?

foreach (Item childItem in item.Children)
{
    var renderings = childItem.Visualization.GetRenderings(Context.Device, false);

    if (renderings.Length > 0)
    {
        var rendering = new Rendering
        {
            RenderingItem = renderings[0].RenderingItem,
            Item = childItem,
            Parameters = new RenderingParameters(renderings[0].RenderingItem.Parameters)
        };

        var writer = new StringWriter();
        var args = new RenderRenderingArgs(rendering, writer);
        PipelineService.Get().RunPipeline("mvc.renderRendering", args);

        output += writer.ToString();
    }
}

2 Answers 2

1

It seems that my code is solid practice, so I did some more digging and found a way to solve my problem of getting the parameters from any given item. I made this into an extension method and I call it when instantiating my rendering.

var layout = LayoutDefinition.Parse(LayoutField.GetFieldValue(item.Fields["__Renderings"]));

if (layout != null && layout.Devices != null && layout.Devices.Count > 0)
{
    var device = (DeviceDefinition)layout.Devices[0];

    if (device != null)
    {
        var renderings = device.Renderings;

        if (renderings != null)
        {
            var writer = new StringWriter();
            var renderingDefinition = renderings.Cast<RenderingDefinition>();
            var parameters = renderingDefinition.FirstOrDefault().Parameters;

            return parameters;
        }
    }
}

return null;

Thanks to this blog by aceanindita I found: https://techmusingz.wordpress.com/2014/08/02/programmatically-access-sitecore-item-presentation/

0

The Controller Renderer

For a while now, I've been using an approach not too dissimilar to what you describe here. In essence, it involves looping over children, picking up a controller name and an action (not too different from your GetRenderings call) and then executing the controller renderings.

Now for my uses, all I need is a specific Datasource for each rendering. But the Rendering I create can also be initialized with RenderingParameters.

The core of it all lies in this bit of code:

var r = new Rendering {DataSource = item.Paths.FullPath};

using (RenderingContext.EnterContext(r))
{
    var runner = new ControllerRunner(controller, action);
    var result = runner.Execute();
    return new HtmlString(result);
}

It's not as generic as your approach; but personally I would never consider anything but Controller Renderings on any solution I'm involved in. I found this to be superior in terms of flexibility.

4
  • I'm aware of your preference for ControllerRenderings, which I appreciate. I typically use them myself. Does this support Areas? And how do you get controller and action ? I this inside of a Controller?
    – Kevin
    Commented Sep 22, 2017 at 17:19
  • Controller and Action are actually part of any template. They are traditionally used with something else entirely (Item Renderings) which I have never really worked out how to use properly. But they are quite suitable for this purpose as well.
    – Mark Cassidy
    Commented Sep 22, 2017 at 17:38
  • Does this honor cache settings?
    – Kevin
    Commented Oct 10, 2017 at 19:50
  • No. But the result you get here is a HtmlString representation of the rendering. This would go into a model of your "outer" rendering - which can and should be cached.
    – Mark Cassidy
    Commented Oct 10, 2017 at 22:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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