Tips for Nested Master Pages and VS 2005 Design-Time

One of the cool advanced features of the new Master Pages feature in ASP.NET 2.0 is the ability to nest them.  For example, you could define a top-level master-page called “MainMaster.master” that defines a common logo header and footer, and defines a content-placeholder for the page called “content”.  You could then define two sub-masters beneath it – one that provides a two-column layout model for the content (“TwoColumnMaster.master”), and one that provides a three-column layout model (“ThreeColumnMaster.master”).  These two nested-master pages could then use the MainMaster.master file as the root master, and only adjust the layout within its content section (each would fill in the "content" placeholder and in turn add their own content-placeholders for sub-pages within it).  The benefit of this approach is that if a designer ever changed the logo or top-level design of the site, they only have to update one file (MainMaster.master) and then have every page on the site automatically pick it up regardless of what master file they were based on.

 

This nested model is pretty cool and powerful, and allows arbitrary levels of nesting.  The only downside is that VS 2005 only supports nested master page editing in source-view, and doesn’t support it in the WYWSIWYG designer (note: obviously it does support editing them when the master-pages are not nested). 

 

There is a cool tip/trick, though, that will allow you to load a design-surface for a page that uses nested master-pages.  This will allow you to use all of the control-designers and smart-tasks in design-view for the page (for example: to perform data-binding, auto-format things, and use any of the control wizards), and not have to change any-code to test it at runtime.

 

The tip/trick works by adding a base-page class to your project or solution that defines a new property called “RuntimeMasterPageFile” of type string.  The base-class then overrides the page’s “OnPreInit” method and uses this property to set the Page object’s MasterPageFile at runtime:

 

public class BasePage : System.Web.UI.Page {

 

    private string runtimeMasterPageFile;

 

    public string RuntimeMasterPageFile {

        get {

            return runtimeMasterPageFile;

        }

        set {

            runtimeMasterPageFile = value;

        }

    }

 

    protected override void OnPreInit(EventArgs e) {

        if (runtimeMasterPageFile != null) {

            this.MasterPageFile = runtimeMasterPageFile;

        }

   

        base.OnPreInit(e);

    }

}

 

Once a code-behind class derives from this base class, it becomes possible for a developer to set this “RuntimeMasterPageFile” property in the .aspx file’s <%@ Page %> directive (note: the CodeFileBaseClass also needs to be set to the base class to enable this):

 

<%@ Page Language="C#"

MasterPageFile="~/Test.master" RuntimeMasterPageFile="SubMaster.master" CodeFileBaseClass="BasePage"

AutoEventWireup="true"

CodeFile="Default.aspx.cs"

Inherits="_Default"

Title="My Page Title" %>

 

You’ll notice that the above page now has two master-page file directives – the usual “MasterPageFile” directive that VS will use at design-time, and then the custom RuntimeMasterPageFile directive that will override this at runtime.  What this allows you to do is point the page at a “test.master” file at design-time that is a single-nested page with contentplaceholder controls that match the names in your nested master.  You can then switch to design-view and edit the content and all controls on your page.  When you run the page, though, it will use the nested “submaster.master” (or any other master page you specify) to run.

 

Update: Brian also pointed out to me that you can leave the MasterPageFile attribute value as "" and the designer will then automatically render a test master page that just lists all of the content-placeholder controls in editable regions.  This might allow you to avoid having to define a test master page for your site.

 

Here is a simple sample that shows all this working (you can switch the default.aspx page to use either the submaster.master or submaster2.master page that is based on mainmaster.master).

 

Hope this helps and is useful,

 

Scott

 

P.S. The new Microsoft Expression “Quartz” Web Designer tool *will* also support editing pages based on nested master-pages in design-time, and this will also show up in the next release of Visual Studio (code-name Orcas).

21 Comments

  • Great tip!, really helpful :)

  • This is very helpful, but still not as easy as it should be. I've noticed that by setting the MasterPageFile to &quot;&quot; the designer will display a page in design mode with no styles, just the basic content boxes. This is exactly what I want for pages that use nested master pages. I'd love an option that would allow that to be the default behavior.



    I don't care about the pretty design-time feature of showing me the entire rendered page. I just want to be able to drag and drop controls onto the page and double-click buttons to have them wire-up. I'm not sure why the default behavior for nested master pages wasn't set to show the basic design surface as is obviously possible, but I feel the decision was a real oversite and severely cripples the MasterPage feature.

  • Looks good, I'll find it useful.

  • Brian -- the MasterPageFile=&quot;&quot; tip is a cool one I hadn't seen before. I agree that would have been good default behavior for the case where it isn't specified.

  • Scott -- Perhaps the default behavior would be a good candidate for the SP release in a few months?



    A beta release of the page designer from Quartz, that worked in 2k5, could be fun.. :)

  • About the MasterPageFile=&quot;&quot; trick, I agree. Also, I am now using it together with the the RuntimeMasterPageFile trick, but not to get nested masters but for regular ones. I do it just because this way I get a larger and more comfortable design surface. It makes me think that it would be nice to have the option not to load the masters at design time.

  • And after I just got a 1.1 page up using a main page with a content pane and swapping out ascx files for the content! Figures... now I want to go play with 2.0...

  • A problem I see with the MasterPageFile=&quot;&quot; trick is that it will render the content in quirks mode.

  • Is this in the final release version? We haven't transitioned our MSDN subscriptions as of yet, so we're on Beta 2. The compiler is complaining about the CodeFileBaseClass attribute and, therefore, RuntimeMasterPageFile.



    Am I missing something, or is this a version difference?



    Cheers

  • Hi James,



    The CodeFileBaseClass attribute is actually only a RTM feature -- it wasn't in the Beta2 build. You could skip making the attribute configurable, though, if you wanted and set the value another way if you wanted to (for example: setting it in the code-behind) as a temporary workaround until you upgrade to RTM.



    Hope this helps,



    Scott

  • Hi,



    I am trying using two nested MasterPages. Let us say the top one is SuperMaster(SuperMaster.master) and I have some controls in this. The other Master Page(SecondMaster.master) which is using SuperMaster.master as Master has some more controls. Now, I will use the approach to set the master page at run time.

    My problem is I am getting the control references from the SuperMaster.master using Master.Master.FindControl(&quot;ControlID&quot;), but I am not getting the control references from the immediate materpage(SecondMaster.master).



    Anybody has Solution???

    Please mail me @ panduranga.kovur@exensys.com

  • Hi, this article seems to be the solution to my problem. Unfortunatly I, being quite new to all this, haven't been able to translate this to VB.NET completely. I get problems with the Protected Overrides OnPreInit. Can somebody translate that part to VB for me? That would be very nice.



    Thanks

  • Fantastic !!

    It took me some time to translate your code to vb.net. But it works splendid.

    Thanks very much

  • Hello again Scott.

    I found another issue with nested Master Pages and Visual Studio 2005:

    You CAN edit the page in source view, but the IDE sometimes loses the "asp" namespace ("Unrecognized namespace 'asp'.", "Unrecognized tag prefix or device filter 'asp'."). It usually clears up if I change the MasterPageFile reference, but sometimes I have to do that and then re-open the file. The problem is somewhat ameliorated if I keep the Code-behind for the Master Page open.

    -Tom

  • Hi Michael,

    That is something that we are looking into more for the "Quartz" engine we are working on (which would also then show up in the next release of Visual Studio).

    BTW -- Scott Allen has some additional good Master Page Articles that you might want to check out here: http://weblogs.asp.net/scottgu/archive/2006/04/18/Great-New-Advanced-Article-on-ASP.NET-2.0-Master-Pages.aspx

    Hope this helps,

    Scott

  • Thanks for the article, it's really useful, I use it when I teach about master pages, thanks.
    This said, master pages are really useful, but I think that the VSteam should have gone a little farther and enable proper design behaviour for the nester MP, that are even more useful.
    bye

  • When page is opened in designer, compiler complains about RuntimeMasterPageFile. Is there a way to let VS.NET 2005 (I'm using Pro version) know that this is not an error, but a valid attribute of directive?
    Thanks

  • Hi Sean,

    You can fix this by turning off the validation option: http://weblogs.asp.net/scottgu/archive/2005/11/23/431350.aspx

    Or you can define/customize your own validation schema using the approach here: http://weblogs.asp.net/scottgu/archive/2006/02/02/437228.aspx

    Hope this helps,

    Scott

  • Hi bill,

    K Scott Allen has a good article on Advanced Master Page techniques that you might want to check out here: http://odetocode.com/Articles/450.aspx

    Hope this helps,

    Scott

  • Great article.
    I've encountered a problem with the nested master file. I cannot get the cs code to pass through the compiler. No matter what is put in that file, it doesn't get compiled.

  • I&#39;ve seen that clearing the content of the MasterPageFile attribute of the @Page let you view the page in design mode with no styles, but stills being awful for us (Developers) &#39;cause we have to set it again when we want to run the application, so trying to fix this i found something that could help, if you don&#39;t remove the content of the MasterPageFile Attribute but you only add a blank space the Runtime will render exactly like if you removed the content with the exception that you haven&#39;t to remove this space when your run your application.
    Example: MasterPageFile=&quot;Admin.master &quot;
    So add a blank space and you&#39;re done!.

Comments have been disabled for this content.