One of the most common questions on the N2CMS forums seems to be how to make it possible to be able to select a master page. In the past when I've worked on cms driven sites the templates have been relatively straightforward - the homepage has had a unique design whilst the others have had a set template. This was quite easy to do as I just created my own class which derived from the StartPage class and then created it's own HTML without using the main MasterPage. Simple, but effective.
However, recently I've been asked to convert an existing Sharepoint site to the MVC version of N2. This has been quite interesting to do and one of the areas I've had to work on is how to give the user the option of which master page template to use. I can't do this statically and because there are a number of templates on the current Sharepoint site it's possible that users may need to change page templates "on the fly".
I'm not going to go to deep in to the workings of this - it's probably easier to fire up N2 MVC and step through the code. I'm going to give you a step-by-step tutorial to get it working!
I'd like to thank the guys on this discussion on the N2CMS forum (n2cms.codeplex.com/discussions?size=2147483647) for providing the inspiration for this. I can't find the exact post however.
Step 1:
Make sure you download the latest v2.1rc MVC version of the site and make sure you copy the DLLs in the library folder into the bin folder of the N2CMS folder. If you don't do this with then you might get an error when you first try to start the site.
Step 2:
In the services folder, open the ThemedMasterViewEngine.cs file. In that there's a method which tries to determine which Master page to use based on theme or uses the there's a class which checks to see what master page to use.
public class ThemedMasterViewEngine : WebFormViewEngine
{
// You should change the "TwoColumnLayout.master" to be your default template
string masterPageFile = "~/Views/Shared/TwoColumnLayout.master";
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if (!controllerContext.IsChildAction)
{
if (string.IsNullOrEmpty(masterName))
masterName = masterPageFile;
var root = Find.Closest<StartPage>(controllerContext.RouteData.CurrentPage()) ?? Find.ClosestStartPage;
if (root != null)
{
string theme = root.Theme;
if (!string.IsNullOrEmpty(theme))
{
string potentialMaster = string.Format("~/Views/Shared/{0}.master", theme);
if (base.FileExists(controllerContext, potentialMaster))
{
masterName = potentialMaster;
}
}
}
}
return base.FindView(controllerContext, viewName, masterName, useCache);
}
}
Step 3:
In the models/pages folder there's a ContentPageBase.cs class. We're going to change this to add an enum for the name of the page templates and add a property for any page which derives from the ContentPageBase (which is all of them) which allows you to select a template and puts it under the Advanced tab.
Open /Models/Pages/ContentPageBaseup and add this code:
public enum PageTemplates
{
MyHomePage,
TwoColumnLayout
}
[EditableEnum("Page layout", 60, typeof(PageTemplates), ContainerName = Tabs.Advanced)]
public virtual PageTemplates PageLayout
{
get { return (PageTemplates)(GetDetail("PageLayout") ?? PageTemplates.TwoColumnLayout); }
set
{
SetDetail("PageLayout", value, PageTemplates.TwoColumnLayout);
}
}
Step 4:
In the controllers folder, open up the TemplatesControllerBase.cs file. We're going to add some code in here which tries to get the name of the PageLayout from the page and sets the master page. Find the method below (be careful - there's a few overloads of it) and replace the method with this code:
protected override ViewResult View(string viewName, string masterName, object model)
{
CheckForPageRender(model);
model = model ?? CurrentItem;
if (model != null)
{
var item = model as N2.Templates.Mvc.Models.Pages.ContentPageBase;
if (!string.IsNullOrEmpty(item.PageLayout.ToString()))
{
masterName = item.PageLayout.ToString();
}
}
return base.View(viewName, masterName, model ?? CurrentItem);
}
Step 5:
I think this might be an oversight in the n2 release, but I've found I have to add this line into the web.config in the n2 editing folder:
<httpRuntime requestValidationMode="2.0" />
Otherwise I get an error when I try to change the page layout.
Step 6:
If you start up your site, and select "Edit" on any page you will find that under the "Advanced" tab you have a drop down list of layouts. If you change this you will be able to change the master page used on the site!