Master Pages
by Microsoft
One of the key components to a successful Web site is a consistent look and feel. In ASP.NET 1.x, developers used user controls to replicate common page elements across a Web application. While that is certainly a workable solution, using user controls does have some drawbacks. For example, a change in position of a user control requires a change to multiple pages across a site. User controls are also not rendered in Design view after being inserted on a page.
One of the key components to a successful Web site is a consistent look and feel. In ASP.NET 1.x, developers used user controls to replicate common page elements across a Web application. While that is certainly a workable solution, using user controls does have some drawbacks. For example, a change in position of a user control requires a change to multiple pages across a site. User controls are also not rendered in Design view after being inserted on a page.
ASP.NET 2.0 introduces Master pages as a way of maintaining a consistent look and feel, and as you'll soon see, Master pages represent a significant improvement over the user control method.
Why Master Pages?
You may be wondering why master pages were needed in ASP.NET 2.0. After all, Web site developers are already using user controls in ASP.NET 1.x to share content areas between pages. There are actually several reasons why user controls are a less-than-optimal solution for creating a common layout.
User controls don't actually define page layout. Instead, they define the layout and functionality for a portion of a page. The distinction between these two is important because it makes manageability of a user control solution much more difficult. For example, when you want to change the position of a user control on your page, you must edit the actual page on which the user control appears. Thats fine if you have only a few pages, but in large sites, it quickly becomes a site management nightmare!
Another drawback of using user controls for defining a common layout is rooted in the architecture of ASP.NET itself. If any public member of a user control is changed, it requires you to recompile all of the pages that use the user control. In turn, ASP.NET will then re-JIT your pages when they are first accessed. This, once again, produces a non-scalable architecture and a site management problem for larger sites.
Both of these problems (and many more) are nicely addressed by master pages in ASP.NET 2.0.
How Master Pages Work
A master page is analogous to a template for other pages. Page elements that should be shared among other pages (i.e. menus, borders, etc.) are added to the master page. When new pages are added to the site, you can associate them with a master page. A page that is associated with a master page is called a content page. By default, a content page takes on the appearance from the master page. However, when you create a master page, you can define portions of the page that the content page can replace with its own content. These portions are defined using a new control introduced in ASP.NET 2.0; the ContentPlaceHolder control.
A master page can contain any number of ContentPlaceHolder controls (or none at all.) On the content page, the content from the ContentPlaceHolder controls appears inside of Content controls, another new control in ASP.NET 2.0. By default, the content pages Content controls are empty so that you can provide your own content. If you want to use the content from the master page inside of the Content controls, you can do so as you will see later in this module. The Content control is mapped to the ContentPlaceHolder control via the ContentPlaceHolderID attribute of the Content control. The code below maps a Content control to a ContentPlaceHolder control called mainBody on a master page.
<asp:Content ID="Content1" ContentPlaceHolderID="mainBody" Runat="Server">
Note
You will often hear people describe master pages as being a base class for other pages. Thats actually not true. The relationship between master pages and content pages is not one of inheritance.
Figure 1 shows a master page and an associated content page as they appear in Visual Studio 2005. You can see the ContentPlaceHolder control in the master page and the corresponding Content control in the content page. Notice that the master pages content that is outside of the ContentPlaceHolder is visible but grayed out in the content page. Only the content inside of the ContentPlaceHolder can be supplanted by the content page. All other content that comes from the master page is immutable.
Figure 1: A master page and its associated content page
Creating a Master Page
To create a new master page:
- Open Visual Studio 2005 and create a new Web site.
- Click File, New, File.
- Choose Master File from the Add New Item dialog as shown in figure 2.
- Click Add.
Figure 2: Creating a New Master Page
Notice that the file extension for a master page is .master. This is one of the ways that a master page differs from an ordinary page. The other primary difference is that in lieu of a @Page directive, the master page contains a @Master directive. Switch to Source View for the master page you've just created and review the code.
A new master page will have one ContentPlaceHolder control by default. In most cases, it makes more sense to create the common page elements first and then insert ContentPlaceHolder controls where custom content is desired. In those cases, developers will want to delete the default ContentPlaceHolder control and insert new ones as the page is developed. ContentPlaceHolder controls are not resizable despite the fact that they do display sizing handles. The ContentPlaceHolder control sizes automatically based upon the content that it contains with one exception; if you place a ContentPlaceHolder control inside of a block element such as a table cell, it will size according to the size of the element.
Lab 1 Working with Master Pages
In this lab, you will create a new master page and define three ContentPlaceHolder controls. You will then create a new Content page and replace the content from at least one of the ContentPlaceHolder controls.
Create a master page and insert ContentPlaceHolder controls.
- Create a new master page as described above.
- Delete the default ContentPlaceHolder control.
- Select the ContentPlaceHolder control by clicking the shaded top border of the control and then delete it by hitting the DEL key on your keyboard.
- Insert a new table using the Header and side template as shown in figure 3. Change the width and height to 90% each so that the entire table is visible in the designer.
Figure 3
- Place the cursor into each cell of the table and set the valign property to top.
- From the Toolbox, insert a ContentPlaceHolder control in the top cell of the table (the header cell.)
- When you insert this ContentPlaceHolder control, you will notice that the row height will take up almost the entire page as shown in figure 4. Don't be concerned about that at this point.
Figure 4: The empty space is in the same cell as the ContentPlaceHolder
- Place a ContentPlaceHolder control in the other two cells. Once the other ContentPlaceHolder controls have been inserted, the size of the table cells should be as you would expect. The page should now look like the page shown in figure 5.
Figure 5: The Master with all ContentPlaceHolder controls. Notice that the cell height for the header cell is now what it should be
- Enter some text of your choice into each of the three ContentPlaceHolder controls.
- Save the master page as exercise1.master.
- Create a new Web Form and associate it with the exercise1.master master page.
- Select File, New, File in Visual Studio 2005.
- Select Web Form in the Add New Item dialog.
- Make sure that the Select master page checkbox is checked as shown in figure 6.
Figure 6: Adding a new Content Page
- Click Add.
- Select exercise1.master in the Select a master page dialog as shown in figure 7.
- Click OK to add the new content page.
The new content page appears in Visual Studio with one Content control for each ContentPlaceHolder control on the master page. By default, the Content controls are empty so that you can add your own content. If you'd like for them to use the content from the ContentPlaceHolder control on the master page, simply click on the smart tag symbol (the small black arrow in the upper-right corner of the control) and choose Default to Masters Content from the smart tag as shown in figure 8. When you do so, the menu item changes to Create Custom Content. Clicking it at that point removes the content from the master page allowing you to define custom content for that particular Content control.
Figure 7: Setting a Content Control to Default to the Master Pages Content
Connecting Master Page and Content Pages
The association between a master page and a content page can be configured in one of four different ways:
- The MasterPageFile attribute of the @Page directive
- Setting the Page.MasterPageFile property in code.
- The <pages> element in the applications configuration file (web.config in the root folder of the application)
- The <pages> element in a subfolders configuration file (web.config in a subfolder)
MasterPageFile Attribute
The MasterPageFile attribute makes it easy to apply a master page to a particular ASP.NET page. It is also the method used to apply the master page when you check the Select Master Page checkbox as you did in Exercise 1.
Setting Page.MasterPageFile in Code
By setting the MasterPageFile property in code, you can apply a particular master page to your content at runtime. This is useful in cases where you may need to apply a specific master page based upon a users role or some other criteria. The MasterPageFile property must be set in the PreInit method. If it is set after the PreInit method, an InvalidOperationException will be thrown. The page on which this property is being set must also have a Content control as the top-level control for the page. Otherwise an HttpException will be thrown when the MasterPageFile property is set.
Using the <pages> Element
You can configure a master page for your pages by setting the masterPageFile attribute in the <pages> element of the web.config file. When using this method, keep in mind that web.config files lower in the application structure can override this setting. Any MasterPageFile attribute set in a @Page directive will also override this setting. Using the <pages> element makes it simple to create a master master page that can be overridden if necessary in particular folders or files.
Properties in Master Pages
A master page can expose properties by simply making those properties public within the master page. For example, the following code defines a property called SomeProperty:
private string _SomeProperty; public string SomeProperty { get { return _SomeProperty; } set { _SomeProperty = value; } }
To access the SomeProperty property from the Content page, you will need to use the Master property like so:
void Page_Load() { Master.SomeProperty = "Master Page Property"; }
Nesting Master Pages
Master pages are the perfect solution for ensuring a common look and feel across a large Web application. However, it's not uncommon to have certain parts of a large site share a common interface while other parts share a different interface. To address that need, multiple master pages are the perfect solution. However, that still doesn't address the fact that a large application may have certain components (such as a menu, for example) that are shared among all pages and other components that are shared only among certain sections of the site. For that type of situation, nested master pages fill the need nicely. As you've seen, a normal master page consists of a master page and a content page. In a nested master page situation, there are two master pages; a parent master and a child master. The child master page is also a content page and its master is the parent master page.
Here is the code for a typical master page:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="parent.master.cs" Inherits="parent" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Typical Master Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:contentplaceholder id="MainMenuContent" runat="server" /> </div> </form> </body> </html>
In a nested master scenario, this would be the parent master. Another master page would use this page as its master page, and that code would look like this:
<%@ Master Language="C#" MasterPageFile="~/parent.master" AutoEventWireup="true" CodeFile="child.master.cs" Inherits="child" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainMenuContent" Runat="Server"> <span>From the Child Master.</span> <asp:contentplaceholder id="ChildPlaceHolder1" runat="server" /> </asp:Content>
Note that in this scenario, the child master is also a content page for the parent master. All of the child master's content appears inside of a Content control that gets its content from the parent's ContentPlaceHolder control.
Note
Designer support is not available for nested master pages. When you are developing using nested masters, you will need to use source view.
This video shows a walkthrough of using nested master pages.
Figure 8: Selecting a Master Page