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!
This is great. Do you have any guidance on how to define custom routes that use content pages? For example, I want to pass route data to a page like /mypage/new/mode. The mypage is the content page and /new/mode are custom route data. Thanks again for the blog.
ReplyDeleteHi "Sales Department"!
ReplyDeleteI am not 100% sure what you are looking for - can you expand on what you are trying to achieve? If you can I might be able to help. You can of course pass data via the querystring which may be a bit easier that writing custom routes. Is there any particular reason why you are looking to do this?
Our existing site has custom routes using asp.net webforms. We were hoping to keep the same urls without changing to query strings. We have one page that has multiple modes and and id field we pass into it. We were hoping to just publish /mypage in n2cms then use custom routes to pass querystring or route data to it. I haven't figured out how to do it yet. Any guidance or help would be great.
ReplyDeleteThanks that's helped me a lot. Keep up good work.
ReplyDeleteThanks that's helped me a lot too. But I run into a problem. If I add a News Container to the Site I can't change the layouts. It's always take my default template even if I choose another template. ;-( What should I do to make the News Container work with different layouts? Thanks again for this good work!
ReplyDeleteHi Anette,
ReplyDeleteHmm... I haven't used the news container on any of my sites yet so I can't really advise on this one. I'm surprised it works for the others apart from the news container.
If I can get a little time over the next couple of days I'll see if there's anything I can suggest!
I'm unsure why, but I cannot appear to get this to work.
ReplyDeleteIf I try to implement Step 5, then I always get an error. If I don't implement Step 5, then the pages will all load, but there's no "Advanced" tab that appears on the page to change to a different layout page.
There is (in my version of web.config) an instance of the Step 5 code, but it was commented out in the initial code from the installation. So ..... I'm a little confused.
Following up on the last post.
ReplyDeleteI've started from scratch and completely re-done this entire process, but getting a number of errors now in the attempted debug/build process in VS2010.
This just does not appear to be working for me and I'm pretty confident that I've followed everything correctly.
Really not sure what's happening here. Please help!
Hi Steve
ReplyDeleteCan you tell me what errors you're getting?
Hi There...
ReplyDeletebeen a while since your response. I'm sorry for the slow followup.
I actually posted the last two posts on here from 4/13. Same issue appears from the first 4/13 post - there is no Advance Tab appearing on the page. I can't see any location to change the layout on a specific page.
Nudge....
ReplyDeleteStill having this error. Any further help?
OK -- Updates: Using VS 2010
ReplyDeleteERROR: ContentPageBase.cs / STEP 3
The modifier 'virtual' is not valid for this item
(FROM THIS LINE)
public virtual PageTemplates PageLayout
ERROR: Expected class, delegate, enum, interface, or struct
FROM SAME LINE ABOVE
Hi SteveF
ReplyDeleteSorry I've not been around recently and haven't had time to look at any N2 stuff recently as I've been working on other projects. I'll see if I can squeeze sometime in over the next week to look at your problem.
Cheers!
This comment has been removed by the author.
ReplyDeletePlz help in n2cms mvc responsive homepage design
ReplyDeleteI was able to find good info from your blog posts.
ReplyDeleteHalfords Give Us A Steer
Banfield Pet Hospital