A client recently had a need for using multiple instances of a single sub-layout that had Sitecore placeholders on it. They discovered that when they tried implementing this, they ended up with duplicate / replicated data in each placeholder of the sub-layout that was used multiple times. Searching for an answer, we came across this excellent post: Dynamic Placeholder Keys in Sitecore. The only problem is that my client is working on the 6.6 Technical Preview version of Sitecore, and their code is in MVC. The solution provided by that blog post needs some adjusting to work in an MVC environment. This blog post will show you how to do that adjustment so that you are able to create Dynamic Placeholders using Sitecore 6.6 and MVC.
First, some more specific details regarding our problem: I have a Controller Rendering named TwoColumns defined within Sitecore. My corresponding cshtml View has 2 Sitecore placeholders (“Column1”,”Column2”) defined using the OOTB Sitecore HTML helper (IE: @Html.Sitecore().Placeholder(“Column1”)). I then have a page template where I want to reuse my TwoColumns rendering multiple times, as the following picture depicts:
You’ll notice in my picture that I have 3 instances of “TwoColumns” defined, and I am placing a PromotionSpot rendering in each of my “Column1” / “Column2” placeholders contained in my TwoColumns rendering. Without going off on too large a tangent, my PromotionSpot control is set up to render a single line of text above a single image. Thus, the details show that I want 6 total promotions in a 2×3 grid layout. (I am also demoing this on a site that is using an example of the MVC Music Store coupled into Sitecore 6.6.) When I go to my page however, I see the following:
My screenshot is zoomed out, but you should clearly be able to make out 10 full pictures and the top of 2 more – remember, I was going for only 6 total. What happens is that Sitecore is putting each of my specified PromotionSpot renderings in each of the “Column1” / “Column2” placeholders, just like my details tell it to do. Hopefully the above demonstrates the need for a dynamic placeholder – now let’s see how to implement it!
The first thing I need to do is code a class that will have a method to serve as an HTMLHelper for my Dynamic Placeholders. I will also create a method in my class that will allow me to look at the current placeholders on my page and determine if there is already a placeholder with the name of the incoming Dynamic Placeholder on the page. If so, then I will append a “_X” at the end of the placeholder name, where X is an incrementing integer based on the number of times a placeholder exists. The code for my class is the following:
using System;
using System.Web;
using Sitecore.Mvc.Common;
using Sitecore.Mvc.Helpers;
using Sitecore.Mvc.Presentation;
namespace MVCTestSite.Common
{
public static class DynamicPlaceholderClass
{
public static HtmlString DynamicPlaceholder(this SitecoreHelper mySCHelper, string placeholderName)
{
string DynamicKey = GetDynamicKey(placeholderName);
if (!string.IsNullOrWhiteSpace(DynamicKey))
{
placeholderName = DynamicKey;
}
IDisposable disposable = PlaceholderContext.Enter(new PlaceholderContext(placeholderName));
return mySCHelper.Placeholder(placeholderName);
}
private static string GetDynamicKey(string placeHolderName)
{
bool NeedIncrement = false;
int IncrementStep = 0;
var myPlaceholders = ContextService.Get().GetInstances();
foreach (PlaceholderContext myPHContext in myPlaceholders)
{
if (myPHContext.PlaceholderName == placeHolderName || myPHContext.PlaceholderName.StartsWith(placeHolderName + “_”))
{
NeedIncrement = true;
IncrementStep++;
}
}
if (NeedIncrement)
{
placeHolderName += “_” + IncrementStep.ToString();
}
return placeHolderName;
}
}
}
Now that I have my class, I can switch any of my Sitecore HTML helper Placeholder calls that will be reused on a single page to DynamicPlaceholders. To do this, I open up my TwoColumns.cshtml view and adjust the Placeholder(“ColumnX”) to the following: @Html.Sitecore().DynamicPlaceholder(“Column1”). Note that I also added my namespace (“MVCTestSite.Common”) to the /Views/Web.config file so that Visual Studio intellisense picked up my DynamicPlaceholder HTML helper.
After that, my coding changes are done. If I now refresh my previous page, I see the following:
I now only have 6 images showing, exactly what I was expecting, and so that must be it, right? Not quite – upon closer inspection, while my result is what I’m looking for, the output of my HTML page shows that all of my promotion spots are in my first instance of TwoColumns – the bottom two are completely empty. This is because my DynamicPlaceholder class has set up 6 placeholders with different names – Column1 / Column2 / Column1_1 / Column2_1 / Column1_2 and Column2_2. But my presentation details are still set up to put my PromotionSpot in Column1 / Column2 only. I should now adjust this on my template as follows:
Notice that I’ve adjusted my last 2 sets of PromotionSpots to go into different placeholders. Thanks to my class code, I can be sure that each subsequent DynamicPlaceholder will get a “_X” appended to the end of the name, so I know exactly where to put my renderings. After a publish, my page now looks exactly like I want it to:
So there you have the code to create Dynamic Placeholders using MVC and Sitecore 6.6!
Hi Jamie,
Do you have the complete working code available as a download or in something like GitHub?
I’ve been trying to get this to work for hours, but still haven’t succeeded.
The Placeholders don’t get the proper naming in my solution and I would really be helped if I could get your code (assuming it works :-))
Best regards,
Ruud van Falier
Hi Ruud
I think I’m dealing with the same problems that you were having. Have you ever found a solution to this?
Thanks,
Serge
Hi Serge,
I ended up asking this on StackOverflow and the answer I got there helped me out:
http://stackoverflow.com/questions/15134720/sitecore-dynamic-placeholders-with-mvc
Hope that helps!
In the next few weeks I might release it as module on the marketplace.
Best regards,
Ruud
See this link for a working solution.
http://stackoverflow.com/questions/15134720/sitecore-dynamic-placeholders-with-mvc
Hi Ruud
I had just refreshed the page but your post didn’t show up so I posted the link which I found in the meantime as well (which as it turns out you had already posted earlier today).
Well anyways, that did help and it works perfectly.
A module would be convenient I guess, good luck with that.
Thanks for your help.
Regards,
Serge
Awesome, this was the simple and best solution. 10/10
Perfect explanation….