3

I'm currently having some issues, while trying to render a sublayout programatically on the server-side. Basically, I want to render a sublayout found on the item myItem, that has a single rendering (sublayout) on it. The criteria is that it should render out correctly for normal mode and Experience Editor mode.

Currently, this is what I've done:

var builder = new StringBuilder();
using (StringWriter writer = new StringWriter(builder))      
using (HtmlTextWriter htmlWriter = new HtmlTextWriter(writer))
{

    var renderings = myItem.Visualization.GetRenderings(Sitecore.Context.Device, true);
    foreach (var rendering in renderings)
    {
        var renderControl = rendering.GetControl();

        rendering.Settings.DataSource = myItem.Paths.FullPath;

        renderControl.RenderControl(htmlWriter);
    }
}

var output = builder.ToString();

Looking at the output, this is empty. I've also tried just to call the RenderControl() and output it to a string, which is then set to null. I should also note, that I do have a PageContext in the control where this code is executed. I can also verify that I can add the renderControl as a child to a ASP placeholder control, which then renders out correctly - but only for preview mode, since is doesn't render the control out with support for the Experience Editor.

What am I missing?

3

While this is an example of rendering a Controller Rendering, I believe it will help you - the basic principles should be the same. Specifically I think, entering a RenderingContext is what you might be missing.

    public virtual HtmlString RenderItem(string idOrPath, string controller, string action)
    {
        Assert.ArgumentNotNullOrEmpty(idOrPath, nameof(idOrPath));
        Assert.ArgumentNotNullOrEmpty(controller, "controller");
        Assert.ArgumentNotNullOrEmpty(action, "action");
        var r = new Rendering();
        r.DataSource = idOrPath;

        return RenderItem(r, controller, action);
    }

    public virtual HtmlString RenderItem(Rendering rendering, string controller, string action)
    {
        Assert.ArgumentNotNull(rendering, nameof(rendering));
        Assert.ArgumentNotNullOrEmpty(controller, "controller");
        Assert.ArgumentNotNullOrEmpty(action, "action");

        using (RenderingContext.EnterContext(rendering))
        {
            var runner = new ControllerRunner(controller, action);
            var result = runner.Execute();
            return new HtmlString(result);
        }
    }
  • Good point, I'll see if that can be applied to my problem. – Søren Engel Oct 18 '16 at 10:59
3

I ended up getting it working, but not using the RenderControl() method. It turns out, that I could just call the GetControl() to get the control for the sublayout afterall, and append that control to the child controls for the actual view. Moreover, I found that it was necessary to set the datasource, before calling the GetControl() method:

var renderings = myItem.Visualization.GetRenderings(Sitecore.Context.Device, true);
foreach (var rendering in renderings)
{
    rendering.Settings.DataSource = myItem.Paths.FullPath;

    Control control = rendering.GetControl();
    this.Controls.Add(control); // There 'this' refers to the actual View
}

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.