Scenario: A layout has controller rendering and it is in main placeholder. When the page loads and hits the action, we are trying to insert an existing WFFM form to the same placeholder as given in this link. This way, we have the option to conditionally load different forms to the same placeholder.

In above mentioned article, it states that, it is possible to insert an existing form onto a page using the code-behind class. By getting hold of placeholder and adding a control to it.

But when the page loads and hits the controller action, this code segment's 3rd line gives null reference error

FormRender fr = new FormRender(); 
fr.FormID = "5D9E85F3-5E03-49A7-A136-93269DEA22A7";//form item id
Sitecore.Context.Page.GetPlaceholder("main").Controls.Add(fr);

The reason is, Sitecore.Context.Page returns 0 placeholder, hence null reference exception as 'GetPlaceholder("main") gives null.

But this code segment, returns placeholder, taken from here

var placeholderName = "my-placeholder";
var renderingReferences = Sitecore.Context.Item.Visualization.GetRenderings(Sitecore.Context.Device, true);
var renderingsInPlaceholder = renderingReferences.Where(r => r.Placeholder.StartsWith(placeholderName, StringComparison.OrdinalIgnoreCase));
var numberOfRenderingsInPlaceholder = renderingsInPlaceholder.Count();

Yes, we can get hold of the placeholder but then how can we add a control/form to this placeholder?

up vote 3 down vote accepted

If memory serves, the GetPlaceholder() method dates from the WebForms era of Sitecore. I don't think it works correctly with MVC layouts, as pages don't get rendered in the same way any more. I tried a quick test, and if I iterate the contents of Sitecore.Context.Page.Placeholders (which GetPlaceholder() uses internally) then I see different results on a WebForms and MVC page. Webforms gives me a list of Placeholder objects, but on MVC the collection is empty. So that's probably why you get a null reference when you ask for a specific placeholder.

The second bit of code you cite looks like it's working on the Presentation Details data that Sitecore keeps as XML to describe what components are bound to a page's placeholders. You can modify this data to dynamically change what components are rendered on a page, but you have to do it before Sitecore starts the process of turning the XML data into a page.

If you want to go down that road, I think you may find this blog post about dynamically injecting presentation components in MVC helpful, as it shows how you can modify the pipeline Sitecore uses to work out the Presentation Details before rendering a page: https://mycodeperks.wordpress.com/2015/08/02/injecting-controller-renderings-at-run-time-in-sitecore-mvc-page/

However I'm not sure that's the right model for the scenario you're describing, as it means the code to decide what form to bind has to live outside of your view/controller. So alternatively can your view statically bind the WFfM form component in your code, but then use logic to specify a different datasource item for it, to choose which form you wish to render?

A view could include something like: (Typed from memory - may not be quite right)

@{ 
    var formID = // some logic to determine the item ID of the form to be displayed
}

Your markup...
<div>
    @Html.Sitecore().Rendering("<ID of the WFfM Form Control>", new { DataSource = formID })
</div>
Your markup...

This blog post talks a bit more about binding MVC components statically like this: https://ctor.io/specify-datasource-item-of-a-statically-binded-rendering/

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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