If you start building very customized websites with Orchard CMS you will soon realize you need to be able to render shapes differently in different zones. You have options when the shapes differ by page, by using display alternates and modules such as Url Alternates. These can get you only so far.
In my scenario, I needed to render the User core shape in two different zones on the same page. If you look at the ThemeMachine Theme's Layout.cshtml you will see that the User shape is being dynamically injected into the Footer :
WorkContext.Layout.Footer.Add(New.User(), "10"); // Login and dashboard links
This is great, because it is dynamically inserting the Login and Dashboard links into the footer for you right from the Layout file. I ended up adding a second entry for my Header Login links as well :
WorkContext.Layout.Navigation.Add(New.User(), "10"); // Login and dashboard links
At this point I now have the User shape going to two different zones on every page. This way the user can login at the top or bottom of my site. I then added a User.cshtml file into my Views folder of my theme and copied the code from Orchard.Web\Core\Shapes\Views\User.cshtml and placed it into this file. After running the site all looked good! I was able to override the Core Shape rendering with my new Theme specific User.cshtml file as needed!
This was good enough until I saw the design. It called for the links to look different in the Navigation and Footer Zones. I spent some time trying to figure out how to either switch of Zone name in my User.cshtml file and also adding a dynamic property to my User shape as well. I wasn't getting anywhere with that, and the only Zone alternates available are for Widgets. (WidgetName-Zone.cshtml). I remembered I had done some work on inserting alternates on the fly prior, but could not find that code.
I reached out to Orchard master Sipke Schoorstra @sfmskywalker and he helped me out with a quick code solution inside Layout.cshtml :
var userNavigation = New.User();
userNavigation.Metadata.Alternates.Clear();
userNavigation.Metadata.Alternates.Add("User__Navigation");
var userFooter = New.User();
userFooter.Metadata.Alternates.Clear();
userFooter.Metadata.Alternates.Add("User__Footer");
WorkContext.Layout.Navigation.Add(userNavigation, "10"); // Login and dashboard links
WorkContext.Layout.Footer.Add(userFooter, "2"); // Login and dashboard links
As you can see above we are just creating a new User shape and then adding to its Alternates collection. All great....just needed to know that sweet syntax. I then created a view template for each. User-Footer.cshtml and User-Navigation.cshtml. Now I can switch the display based on Zone!
About the Author:
Arra Derderian serves as the President and as a Lead Technical Architect for Cloud Construct. As a founder at Cloud Construct, Arra is involved in all levels of the business from new project engagements, project planning, and development.
He also serves as the founder of the Boston Orchard CMS User Group and is a member of the Windows Azure Insiders group.
Arra graduated from Northeastern University School with a Bachelor of Science degree in Computer Science.