Master Pages in ASP.NET 2.0

 

Stephen Walther
Superexpert

August 2004

Applies to:
   Microsoft ASP.NET 2.0

Summary: Master Pages enable you to create ASP.NET pages that follow a consistent theme and style. Stephen Walther shows you how to take advantage of this new feature. (27 printed pages)

Contents

Introduction
Master Pages and Content Pages
Creating a Simple Master Page
Creating a Simple Content Page
Creating a Master Page with Site Navigation
Nesting Multiple Master Pages
Configuring Master Pages
Overriding Master Page Properties
Using the Page Title Attribute
Overriding HTML Header Attributes
Exposing Properties and Methods from a Master Page
Dynamically Loading Master Pages
Conclusion
Related Books

Introduction

Master Pages, a new feature of Microsoft ASP.NET 2.0, enable you to apply the same page layout to multiple content pages in a Web application. Master Pages provide you with an easy method of creating a consistent look and feel for a Web site.

The pages in most Web applications have standard elements, such as logos, navigation menus, and copyright notices. You can place all of these elements within a single Master Page. If you base the content pages in your application on this Master Page, then all of the content pages will automatically include the same standard elements.

In this article, you'll learn how to take advantage of Master Pages in order to create standard page layouts. We'll also explore some of the advanced features of Master Pages. For example, you'll learn how you can modify header properties, such as page titles and meta tags from a content page. You'll also learn how to dynamically load different Master Pages at run time.

Master Pages and Content Pages

Let's start by creating a simple Master Page. You can create Master Pages by using Notepad. Or, you can take advantage of Microsoft Visual Web Developer to get full designer support while building Master Pages (see Figure 1). Creating Master Pages with Visual Web Developer is more fun, but I won't assume that you are using Visual Web Developer in this article.

ms379585.masterpages_fig01(en-US,VS.80).gif

Figure 1. Designer support for Master Pages

Creating a Simple Master Page

You create a Master Page in pretty much the same way as you create a normal ASP.NET page. A Master Page can contain the same Web controls, User controls, HTML content, and scripts that you would add to a standard ASP.NET page. There are three important differences between a Master Page and a normal ASP.NET page.

First, unlike a normal ASP.NET page, the name of a Master Page must end with the special extension .master. This extension marks the page as a Master Page. Furthermore, an ASP.NET application is configured so that you cannot request pages with the .master extension. It doesn't make sense to request a Master Page directly. Instead, you request content pages based on the Master Page.

Second, a Master Page includes a <%@ Master %> directive instead of the normal <%@ Page %> directive. The <%@ Master %> directive supports many of the same attributes as the <%@ Page %> directive. For example, you can specify the programming language of the page with the directive <%@ Master Language="vb" %>.

The final difference between a Master Page and a normal ASP.NET page is that a Master Page can contain zero or more ContentPlaceHolder controls. A ContentPlaceHolder control can be used only within a Master Page. This control marks an area of a Master Page that can be overridden by a particular content page.

The Master Page in Listing 1, named Simple.master, contains an HTML table with two ContentPlaceHolder controls.

Listing 1. Simple.master

<%@ Master %>
<html>
<head>
    <title>Simple Master Page</title>
</head>
<body>
<form id="form1" runat="server">
<table width="100%">
<tr>
    <td>
    <asp:ContentPlaceHolder 
        id="ContentPlaceHolder1" 
        runat="server" />
    </td>
    <td>
    <asp:ContentPlaceHolder 
        id="ContentPlaceHolder2" 
        runat="server" />
    </td>
</tr>
</table>
</form>
</body>
</html>

The Master Page in Listing 1 contains two ContentPlaceHolder controls named ContentPlaceHolder1 and ContentPlaceHolder2. These two controls mark the areas of the Master Page that can be modified in the case of particular content pages. If you open the Master Page in Listing 1 within the Visual Web Developer designer, you'll see the page in Figure 2.

ms379585.masterpages_fig02(en-US,VS.80).gif

Figure 2. The Simple.master Master Page

Notice that the Master Page in Listing 1 contains the standard opening HTML tags. For example, it includes the HTML <title> and <body> tags. You'll typically want to include these standard tags in the Master Page. Later in this article (in the section entitled "Overriding Master Page Properties"), we'll discuss how you can change the title in particular content pages.

Furthermore, notice that the Master Page includes the server-side <form> tag. Since you are allowed only one server-side <form> tag in an ASP.NET page, you'll almost always want to include this tag within the Master Page.

Creating a Simple Content Page

After you create a Master Page, you can base one or more content pages on the Master Page. A content page is the actual page that you request from your Web browser. A content page has the same .aspx extension as a normal ASP.NET file. It is similar to a normal ASP.NET page with two very important exceptions.

First, all content in a content page must be contained within Content controls. The Content controls are used to map the content areas in a content page to the content areas marked by the ContentPlaceHolder controls in a Master Page.

Second, a content page must be associated with a Master Page. You can associate a content page with a Master Page by using an attribute of the <%@ Page %> directive. Alternatively, you can use a Web configuration file to associate multiple content pages with a Master Page.

For example, the content page in Listing 2 contains two Content controls, which correspond to the ContentPlaceHolder controls in the Master Page in Listing 1.

Listing 2. Simple.aspx

<%@ Page MasterPageFile="~/Simple.master" %>
<asp:Content 
    ID="Content1" 
    ContentPlaceHolderID="ContentPlaceHolder1" 
    Runat="server">
    Content in Left Column
</asp:Content>
<asp:Content 
    ID="Content2" 
    ContentPlaceHolderID="ContentPlaceHolder2" 
    Runat="server">
    Content in Right Column
</asp:Content>

The content page in Listing 2 includes a MasterPageFile attribute in its <%@ Page %> directive. This attribute associates the content page with the Master Page in Listing 1.

Notice that both Content controls include text in between their opening and closing tags. In this case, the Content controls simply contain text. However, you can add just about any content you want within the Content controls, including Web controls and User Controls.

When you edit a content page in Visual Web Developer, you can see the Master Page ghosted in the background (see Figure 3). Visual Web Developer will automatically add Content controls that correspond to each ContentPlaceHolder from the Master Page.

ms379585.masterpages_fig03(en-US,VS.80).gif

Figure 3. Editing content page in Visual Web Developer

Creating a Master Page with Site Navigation

The Master Page and content page discussed in the previous section are over simplified. In real life, you'll want to add standard navigation elements, such as a menu bar and bread crumb trail, to a Master Page. In this section, we'll walkthrough the process of creating a more realistic Master Page (see Figure 4).

ms379585.masterpages_fig04(en-US,VS.80).gif

Figure 4. A more complicated Master Page

Our Master Page will contain both a SiteMapPath control and Menu control for navigation. The SiteMapPath control displays a bread crumb trail, and the Menu control displays a navigation menu. Both of these controls will use the SiteMap file in Listing 3.

Listing 3. web.sitemap

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
    <siteMapNode url="~/Default.aspx" title="Home">
   <siteMapNode url="~/Products.aspx" title="Products"/>
   <siteMapNode url="~/Services.aspx" title="Services"/>
    </siteMapNode>
</siteMap>

The SiteMap file in Listing 3 defines three nodes: a home page, a products page, and a services page. Each node has a both a URL and title attribute specified. The Master Page in Listing 4 takes advantage of this file for its SiteMapPath and Menu controls.

Listing 4. NavMaster.master

<%@ Master %>
<html>
<head>
    <title>NavMaster</title>
</head>
<body>
    <form id="form1" runat="server">

        <table 
            width="100%"
            border="0"
            cellpadding="5">
        <tr>
            <td colspan="2">
            <asp:Image 
                id="Image1"
                ImageUrl="~/Logo.gif" Runat="Server" />
            </td>
        </tr>
        <tr bgcolor="lightblue">
            <td colspan="2">
            <asp:SiteMapPath 
                id="SiteMapPath1" 
                Runat="Server" />             
            </td>
        </tr>
        </table>
        <table width="100%" cellpadding="10" border="0">
        <tr>
            <td valign="top" width="100" bgcolor="#eeeeee">
            <asp:Menu 
                id="Menu" 
                Runat="Server" 
                DataSourceID="SiteMapDataSource1" 
                StaticDisplayLevels="2" />
            </td>
            <td valign="top">
            <asp:contentplaceholder 
                id="ContentColumn" 
                runat="server" />
            </td>
            <td valign="top" width="100" bgcolor="#eeeeee">
            <asp:ContentPlaceHolder 
                id="AdColumn" 
                runat="server">
                <asp:Image
                    ID="Ad1" 
                    ImageUrl="Ad1.gif"
                    Runat="Server" />
                <br />
                <asp:Image
                    ID="Ad2"  
                    ImageUrl="Ad2.gif"
                    Runat="Server" />
            </asp:ContentPlaceHolder>
            </td>
        </tr>
        </table>     
        <small>All contents copyright &copy; 
  2004 by Microsoft Hair Stylists</small>
        <asp:SiteMapDataSource ID="SiteMapDataSource1" 
  Runat="server" />
    </form>
</body>
</html>

The Master Page in Listing 4 contains two ContentPlaceHolder controls. The first ContentPlaceHolder control is used as a placeholder for the main page content and the second ContentPlaceHolder control is used as a placeholder for advertising content.

The second ContentPlaceHolder control contains default content. It contains two Image controls that are used to display banner advertisements (see Figure 5). This default content can be overridden within particular content pages.

ms379585.masterpages_fig05(en-US,VS.80).gif

Figure 5. The NavMaster.master Master Page

Finally, the content page in Listing 5 is based on the NavMaster.master Master Page (see Figure 6). This page contains a single Content control that contains content for the main content area of the Master Page.

ms379585.masterpages_fig06(en-US,VS.80).gif

Figure 6. The Products.aspx Page

Listing 5. Products.aspx

<%@ Page MasterPageFile="~/NavMaster.master" %>
<asp:Content 
    ID="Content1" 
    ContentPlaceHolderID="ContentColumn" 
    Runat="server">
    This is the Products.aspx page
</asp:Content>

Nesting Multiple Master Pages

So far, we've looked at how you can create a single Master Page and base a content page on the Master Page. A single Web site can contain multiple Master Pages. For example, you can create distinct Master Pages for distinct sections in a Web site.

Furthermore, if you have the need, you can even nest multiple Master Pages. For example, you can create one Master Page for the entire Web site and then nest Master Pages below the site Master Page for individual sections. Visual Web Developer does not provide designer support for doing this. So, if you want to nest Master Pages, you'll need to stick to either source code view or build your pages using Notepad.

For example, the page in Listing 6 could be used for a Site Master Page. This Master Page contains the opening and closing HTML and Form tags and a single ContentPlaceHolder control.

Listing 6. SiteMaster.master

<%@ Master %>
<html>
<head>
    <title>Site Master</title>
</head>
<body bgcolor="LightGreen">
    <form id="form1" runat="server">
        <h1>Site Master Page</h1>
        <asp:contentplaceholder 
            id="SiteContentPlaceHolder" 
            runat="server" />
    </form>
</body>
</html>

The page in Listing 7 is a nested Master Page. This Master Page overrides the content in the Site Master Page. Notice that the <%@ Master %> directive refers to the SiteMaster.master Master Page.

Listing 7. SectionMaster.master

<%@ Master  MasterPageFile="~/SiteMaster.master" %>
<asp:content
    ContentPlaceHolderID="SiteContentPlaceHolder" 
    runat="server">
    
    <table width="100%" bgcolor="LightYellow">
    <tr>
        <td colspan="2">
        <h1>Section Master Page</h1>
        </td>
    </tr>
    <tr>
        <td>
        <asp:ContentPlaceHolder   
            id="LeftColumn"
            Runat="Server" />     
        
        </td>
        <td>
        <asp:ContentPlaceHolder   
            id="RightColumn"
            Runat="Server" />     
        </td>
    </tr>
    </table>
    
</asp:content>

Finally, the content page in Listing 8 is based on the Section Master Page. Notice that this page overrides the two ContentPlaceHolder controls contained in the Section Master Page.

Listing 8. NestedMasters.aspx

<%@ Page MasterPageFile="~/SectionMaster.master" %>

<asp:Content    
    ContentPlaceHolderId="LeftColumn"
    Runat="Server">

    This content appears in the left column

</asp:Content>


<asp:Content   
    ContentPlaceHolderId="RightColumn"
    Runat="Server">

    This content appears in the right column

</asp:Content>

When all is said and done, the page in Figure 7 is rendered. Notice that the content of the Site Master Page and the Section Master Page are merged to generate the final content page. The content of the Site Master Page appears in green and the content of the Section Master page appears in yellow.

ms379585.masterpages_fig07(en-US,VS.80).gif

Figure 7. A nested Master Page

Configuring Master Pages

Instead of associating a content page with a Master Page by using the <%@ Page %> directive, you can associate a Master Page with a content page within your Web application's configuration file. Using the configuration file makes it easier to maintain large Web sites, since you can change the Master Page associated with many content pages in a single location.

You set the Master Page within the <pages> element of a configuration file. (This element appears in the <system.web> section of a configuration file.) For example, the following <pages> element sets the default Master Page to "SuperMaster.master":

<pages masterPageFile="SuperMaster.master" />

There are two points that you need to be aware of when assigning a Master Page in a configuration file. First, setting a Master Page within a content page takes precedence over any Master Page set in the configuration file. Therefore, if you want to use the Web.Config file to set Master Pages, you should not include the MasterPageFile attribute in your content pages.

Second, your application can contain more than one Web.Config file located in different subfolders that set different Master Pages. In other words, you can override the Master Page set in a Web.Config file within a subfolder by creating a new Web.Config file.

Overriding Master Page Properties

One issue that you encounter almost immediately when working with Master Pages is the issue of how to override such properties as the page title and meta tags of a Master Page in individual content pages. Typically, you want to display unique titles for each content page, even when the individual content pages are based on a shared Master Page.

There are multiple ways of overriding the content contained in a Master Page within a particular content page. We'll explore each of these methods in this section.

Using the Page Title Attribute

If you simply want to change the page title rendered by a Master Page from within a content page, then you can take advantage of the <%@ Page %> directive's Title attribute. This attribute only takes effect when the Master Page uses a server-side HtmlHead control.

For example, the Master Page in Listing 9 contains a server-side HtmlHead control.

Listing 9. TitleMaster.master

<%@ Master %>
<html>
<head runat="server">
    <title>Master Title</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:contentplaceholder 
        id="ContentPlaceHolder1" 
        runat="server" />
    </form>
</body>
</html>

Notice that the <head> tag in Listing 9 includes a runat="server" attribute. This attribute transforms the <head> tag into a server-side HtmlHead control.

The content page in Listing 10 overrides the page title. Notice that the <%@ Page %> directive at the top of this page has a value for its Title attribute. When the page is rendered, the text "Content Page Title" is displayed as the page title.

Listing 10. TitleContent.aspx

<%@ Page MasterPageFile="~/TitleMaster.master" Title="Content Page Title" %>

<asp:Content
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    
    Here is some content
    
</asp:Content>

Overriding HTML Header Attributes

If you need to override other attributes of an HTML header, such as the meta tags or style tags, then you can reference the HtmlHead element directly from a content page. The HtmlHead control implements the IPageHeader interface, which includes the following properties:

  • LinkedStyleSheets—the external style sheets linked to the HTML page.
  • Metadata—the collection of Metadata tags.
  • StyleSheet—represents the styles applied to the HTML page.
  • Title—the title of the HTML page.

You can modify any of these properties within a content page. For example, the Master Page in Listing 11 includes a server-side HtmlHead control that can be overridden in a content page.

Listing 11. HeaderMaster.master

<%@ Master %>

<html>
<head runat="server">
    <title>Master Title</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:contentplaceholder 
        id="ContentPlaceHolder1" 
        runat="server" />
    </form>
</body>
</html>

The content page in Listing 12 modifies both the Title and Metadata properties of the HtmlHead control in order to display custom content.

Listing 12. HeaderContent.aspx (Microsoft Visual Basic .NET)

<%@ Page Language="VB" MasterPageFile="~/HeaderMaster.master" %>

<script runat="server">

    Sub Page_Load()
        Master.Page.Header.Title = "Content Title"
        Master.Page.Header.Metadata.Add("Keywords", "blah,blah")
        Master.Page.Header.Metadata.Add("Description", "blah,blah")
    End Sub
    
</script>

<asp:Content
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    
    Here is some content
    
    </asp:Content> 

Listing 12. HeaderContent.aspx (c#)

<%@ Page Language="c#" MasterPageFile="~/HeaderMaster.master" %>

<script runat="server">

    void Page_Load() {
        Master.Page.Header.Title = "Content Title";
        Master.Page.Header.Metadata.Add("Keywords", "blah,blah");
        Master.Page.Header.Metadata.Add("Description", "blah,blah");
    }
    
</script>

<asp:Content ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    
    Here is some content
    
    </asp:Content>

The Master property of the Page object refers to the Master Page of the content page (You could, if you really wanted to, use Page.Master instead of Master). The Header property refers to the HtmlHead element. The content page in Listing 12 modifies the Title and Metadata properties of the HtmlHead control.

Exposing Properties and Methods from a Master Page

If you need even more control over the content of a Master Page, then you can expose properties and methods from the Master Page. You can modify public properties exposed by a Master Page in a content page. You can call public methods exposed by a Master Page in a content page.

Imagine, for example, that you want to modify the content of a Master Page footer within a content page. The Master Page in Listing 13 exposes a public property named Footer.

Listing 13. FooterMaster.master (Visual Basic .NET)

<%@ Master Language="VB" %>

<script runat="server">

    Private _footer As String
    
    Public Property Footer() As String
        Get
            Return _footer
        End Get
        Set(ByVal value As String)
            _footer = value
        End Set
    End Property
    
</script>

<html>
<head runat="server">
    <title>Footer Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:contentplaceholder 
        id="ContentPlaceHolder1" 
        runat="server" />
    <br />
    <small><%= _footer %></small>
    </form>
</body>
</html>

Listing 13. FooterMaster.master (C#)

<%@ Master Language="C#" %>

<script runat="server">

    private string _footer;
    
    public string Footer {
        get {
            return _footer;
        }
        set {
            _footer = value;
        }
    }
    
</script>

<html>
<head id="Head1" runat="server">
    <title>Footer Master</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:contentplaceholder 
        id="ContentPlaceHolder1" 
        runat="server" />
    <br />
    <small><%= _footer %></small>
    </form>
</body>
</html>

In Listing 13, the public Footer property modifies a private field named _footer. The private _footer field is displayed at the bottom of the Master Page using the inline expression <%= _footer %>.

The content page in Listing 14 sets the Footer property. The Footer property is exposed by the Master property of the Page object. Normally, the Master property represents a MasterPage object. However, this content page includes a <%@ MasterType %> directive that casts the value of the Master property to a FooterMaster object.

Listing 14. FooterContent.aspx (Visual Basic .NET)

<%@ Page Language="VB" MasterPageFile="~/FooterMaster.master" %>
<%@ MasterType VirtualPath="~/FooterMaster.master" %>

<script runat="server">

    Sub Page_Load()
        Master.Footer = "Custom Page Footer"
    End Sub
    
</script>

<asp:Content
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Here is some content    
</asp:Content>

Listing 14. FooterContent.aspx (C#)

<%@ Page Language="C#" MasterPageFile="~/FooterMaster.master" %>
<%@ MasterType VirtualPath="~/FooterMaster.master" %>

<script runat="server">

    void Page_Load() {
        Master.Footer = "Custom Page Footer";
    }
    
</script>

<asp:Content ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Here is some content    
</asp:Content>

By exposing properties and methods in a Master Page, you can modify any aspect of the rendering of a Master Page.

Dynamically Loading Master Pages

In this final section, we'll take a look at an advanced application of Master Pages. We'll examine how you can dynamically load different Master Pages at run time.

There are a couple of circumstances in which dynamically loading Master Pages is useful. First, you might need to co-brand your Web site with one or more partner Web sites. When someone links to your Web site from a partner Web site, you might want to automatically load up a Master Page that matches the look and feel of the partner Web site.

Another situation in which you might want to dynamically load Master Pages is when you want the users of your application to be able to pick a page layout. You can provide your users with a set of standard Master Pages. Users of your application can then select their favorite page layout by selecting their favorite Master Page.

You can dynamically load a Master Page by assigning a value to the MasterPageFile property of the Page object. The value assigned to this property should be a relative path to a valid Master Page file.

There is one important restriction that you must be aware of when using the MasterPageFile property. You can only assign a value to this property before or during the Page PreInit event. The PreInit is the earliest event during the page execution lifecycle. If you attempt to assign a value to this property during a later event, such as the Page Load event, then you'll receive an exception. This restriction makes sense, since different Master Pages will result in different sets of controls being loaded into the page.

The content page in Listing 15 takes advantage of the MasterPageFile property to dynamically load different Master Pages at run time.

Listing 15. DynamicContent.aspx (Visual Basic .NET)

<%@ Page Language="VB" MasterPageFile="~/DynamicMaster1.master" %>

<script runat="server">
    
    Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs)
        MasterPageFile = Profile.Master
    End Sub

</script>

<asp:Content
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Here is the content
</asp:Content> 

Listing 15. DynamicContent.aspx (C#)

<%@ Page Language="c#" MasterPageFile="~/DynamicMaster1.master" %>

<script runat="server">
    
    void Page_PreInit(Object sender, EventArgs e) {
        MasterPageFile = Profile.Master;
    }

</script>

<asp:Content ID="Content1"
    ContentPlaceHolderID="ContentPlaceHolder1"
    Runat="Server">
    Here is the content
</asp:Content>

In Listing 15, a Master Page is dynamically loaded within the PreInit event. In this case, the path to the Master Page file is loaded from the user's profile. You can use a profile to persistently store information associated with a user. That way, as the user travels from page to page within your application, the Master Page the user has selected is not lost.

In order to take advantage of the user profile, you need to add the following configuration settings to the <system.web> section of the application Web.Config file:

<anonymousIdentification enabled="true" />
     
 <profile>
 <properties>
    <add 
   name="Master" 
    allowAnonymous="true" 
   defaultValue="DynamicMaster1.master" />
 </properties>
 </profile>

These settings create a new Profile property named Master that can be used by both anonymous and authenticated users.

The content page in Listing 15 loads one of two Master Pages named DynamicMaster1.master and DynamicMaster2.master. The source code for DynamicMaster1.master is contained in Listing 16 and the source code for DynamicMaster2.master is contained in Listing 17. These Master Pages are identical, except that they have different names and display different background colors.

Listing 16. DynamicMaster1.master (Visual Basic .NET)

<%@ Master Language="vb" %>
<script runat="server">

    Sub Page_Load()
        If Not IsPostBack Then
            dropMaster.SelectedValue = Profile.Master
        End If
    End Sub
    
    Sub SelectMaster(ByVal s As Object, ByVal e As EventArgs)
        Profile.Master = dropMaster.SelectedValue
        Response.Redirect(Request.Path)
    End Sub
    
</script>

<html>
<head>
    <title>Dynamic Master 1</title>
</head>
<body bgcolor="LightYellow">
<form runat="server">
<h1>Dynamic Master 1</h1>
<p>
<asp:DropDownList 
    id="dropMaster"
    AutoPostBack="true"
    OnSelectedIndexChanged="SelectMaster" 
    ValidationGroup="Master" 
    Runat="Server">
    <asp:ListItem Text="Dynamic 1" value="DynamicMaster1.master" />
    <asp:ListItem Text="Dynamic 2" value="DynamicMaster2.master" />
</asp:DropDownList>
</p>
<asp:contentplaceholder 
    id="ContentPlaceHolder1" 
    runat="server" />
</form>
</body>
</html>

Listing 16. DynamicMaster1.master (C#)

<%@ Master Language="c#" %>

<script runat="server">
    
    void Page_Load() {
        if (!IsPostBack)
            dropMaster.SelectedValue = Profile.Master;
        }
    
    void SelectMaster(Object s, EventArgs e) {
        Profile.Master = dropMaster.SelectedValue;
        Response.Redirect(Request.Path);
    }
    
</script>

<html>
<head>
    <title>Dynamic Master 1</title>
</head>
<body bgcolor="LightYellow">
<form id="Form1" runat="server">
<h1>Dynamic Master 1 CS</h1>
<p>
<asp:DropDownList 
    id="dropMaster"
    AutoPostBack="true"
    OnSelectedIndexChanged="SelectMaster" 
    ValidationGroup="Master" 
    Runat="Server">
    <asp:ListItem Text="Dynamic 1" value="DynamicMaster1.master" />
    <asp:ListItem Text="Dynamic 2" value="DynamicMaster2.master" />
</asp:DropDownList>
</p>
<asp:contentplaceholder 
    id="ContentPlaceHolder1" 
    runat="server" />
</form>
</body>
</html>

Listing 17. DynamicMaster2.master (Visual Basic .NET)

<%@ Master Language="vb" %>
<script runat="server">
    Sub Page_Load()
        If Not IsPostBack Then
            dropMaster.SelectedValue = Profile.Master
        End If
    End Sub
    
    Sub SelectMaster(ByVal s As Object, ByVal e As EventArgs)
        Profile.Master = dropMaster.SelectedValue
        Response.Redirect(Request.Path)
    End Sub
    
</script>

<html>
<head>
    <title>Dynamic Master 2</title>
</head>
<body bgcolor="LightGreen">
<form id="Form1" runat="server">
<h1>Dynamic Master 2</h1>
<p>
<asp:DropDownList 
    id="dropMaster"
    AutoPostBack="true"
    OnSelectedIndexChanged="SelectMaster" 
    ValidationGroup="Master"
    Runat="Server">
    <asp:ListItem Text="Dynamic 1" value="DynamicMaster1.master" />
    <asp:ListItem Text="Dynamic 2" value="DynamicMaster2.master" />
</asp:DropDownList>
</p>
<asp:contentplaceholder 
    id="ContentPlaceHolder1" 
    runat="server" />
</form>
</body>
</html>

Listing 17. DynamicMaster2.master (C#)

<%@ Master Language="c#" %>
<script runat="server">
    
    void Page_Load() {
        if (!IsPostBack)
            dropMaster.SelectedValue = Profile.Master;
        }
    
    void SelectMaster(Object s, EventArgs e) {
        Profile.Master = dropMaster.SelectedValue;
        Response.Redirect(Request.Path);
    }
    
</script>

<html>
<head>
    <title>Dynamic Master 2</title>
</head>
<body bgcolor="LightGreen">
<form id="Form1" runat="server">
<h1>Dynamic Master 2 CS</h1>
<p>
<asp:DropDownList 
    id="dropMaster"
    AutoPostBack="true"
    OnSelectedIndexChanged="SelectMaster" 
    ValidationGroup="Master"
    Runat="Server">
    <asp:ListItem Text="Dynamic 1" value="DynamicMaster1.master" />
    <asp:ListItem Text="Dynamic 2" value="DynamicMaster2.master" />
</asp:DropDownList>
</p>
<asp:contentplaceholder 
    id="ContentPlaceHolder1" 
    runat="server" />
</form>
</body>
</html>

Both Master Pages contain a DropDownList control that enables a user to select a particular Master Page. When a user picks a Master Page, the SelectMaster method is called. This method assigns the selected Master Page to the user profile and reloads the current page. The page reload is necessary since the newly selected Master Page must be loaded during the PreInit event.

Conclusion

On a personal note, Master Pages is my favorite new feature of ASP.NET 2.0. This new feature will have the greatest impact on how I build ASP.NET applications in the future. Today, I fumble around with user controls (horrible) or custom base Page classes (really horrible) to create reusable page layouts. Master Pages provide you with a clean and intuitive method of creating reusable page layouts. And, best of all, Microsoft Visual Studio .NET 2005 provides you with full designer support so you can see what your pages will look like while you are building them.

 

About the author

Stephen Walther wrote the best-selling book on ASP.NET, ASP.NET Unleashed. He was also the architect and lead developer of the ASP.NET Community Starter Kit, a sample ASP.NET application produced by Microsoft. He has provided ASP.NET training to companies across the United States, including NASA and Microsoft, through his company Superexpert (https://www.superexpert.com).

© Microsoft Corporation. All rights reserved.