Using ASP.NET Master Pages for Consistent Site Design
By Jacob J. Sanford
Creating one page (Default.aspx) that is aesthetically pleasing, easy to use by your visitors, takes various browsers into consideration, uses CSS, is one thing. Copying this code to every page in your site would be, to say the least, a maintenance nightmare. Can you imagine having to update thousands of pages because the client wants a fairly minor design tweak? What you really want is a way to create a reusable template that can be incorporated into every page of your site. This will allow for all pages to look the same throughout your project while allowing for easier maintenance as your projects mature. In a year or so when you want to redo the entire site, you would only need to change the template rather than the coding on every page of your application. With Master Pages, you can do exactly that.
A Master Page is simply a single page that holds the structure of your Web site. The files are designated with a .master file extension and are imported into content pages through the MasterPageFile property of the @Page directive of the content pages. They are meant to provide the template that all of your pages will use throughout the site. They are not really meant to hold the content of an individual page or, even, the stylistic definitions of the page. They are meant to provide a blueprint of what your site should look like and then connect that template to style rules set in detached CSS files (as appropriate).
Enough Talk; Time to Code
This article will go through the ins and outs of Master Pages. You should start a new project to practice these new concepts. So, with a new Web project open in Visual Studio 2005, click on Website and then choose "Add New Item" to get the screen depicted in Figure 1.
You will want to select "Master Page", ironically enough, as the template you want to use for your new item. You can name the page whatever you want but should leave the .master file extension. You should choose the language you code in, although this isn't particularly relevant unless you want to do any "under the hood" coding in the Master Page itself. Again, while this is possible and pertinent in some situations, for the most part, this is not necessarily relevant for most projects. It should also be noted that the language of the Master Page file will not dictate the language of the content page that inherits it. This just means that you can have a Master Page file that has a language declaration of, say, VB and a content page that inherits it that has a language of C# (or the other way around). To expand this thought, you might have a designer who is responsible for creating the look and feel of your projects and is more comfortable with VB.NET. She could easily create the Master Page in VB without any worry about the coding preferences of the rest of the team. Once the VB Master Page is completed, the developers in the group could code against this VB Master Page in their language of choice (VB or C#). Even if there are public properties or methods in the Master Page that are written in VB, C# content pages can access them. This language independence of Master Pages is one of its nicest features.
However, for this example, just choose whatever language you are more comfortable with and press the "Add" button. This will create a file in your project called "MasterPage.master" that should resemble the following:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> <!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>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:contentplaceholder> </div> </form> </body> </html>
There are a couple of noteworthy elements to the default code provided. The first is the @Page declaration or, in this case, the lack thereof. The declaration statement for a Master Page is the @Master declaration. Other than that, though, the declaration looks pretty much identical to the @Page declaration you are probably used to seeing in other pages you may have created previously. There are Language, AutoEventWireup, CodeFile, and Inherits properties and they are set to intuitive values. In fact, if you compared the @Master declaration to a standard @Page declaration, you wouldn't see any difference except the name of the declaration and the names of the files that are used in the values of the properties just mentioned. They are, in this regard, identical. If you delve into all of the properties available to each, you will see a lot of differences. However, for now, it is sufficient to know that they have some shared properties and that, by default, Visual Studio creates new files with either a @Master or @Page declaration with the same properties in the initial declaration.
The other important thing to notice is the following code in the middle of the file:
<asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:contentplaceholder>
This creates the region in the template that will be filled with material from the content pages created by the programmers. Each content page will reference the ID of this placeholder in its code and stick all of the content from that page in this particular region.
It is worth noting that you are not limited to a single placeholder in your Master Page. You can, in reality, set up as many placeholders as you need for your page. However, in practice, you should probably limit the number used to the number you actually need. If you have, for example, one hundred placeholders in your Master Page, you are probably not centralizing the content enough and, more importantly, are creating a maintenance headache. One placeholder is the default and around two or three are fairly common to see in practice. If you are using much more than that, you should really evaluate how you are using the Master Page and whether there is a simpler way to handle the content.
However, to see how these placeholders might be used in a project, examine the following code:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> <!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>Untitled Page</title> </head> <body bgcolor="navy"> <form id="form1" runat="server"> <div> <table border="0" width="700"> <tr> <td colspan="2" height="150" bgcolor="gray" valign="middle" align="center"> HEADER </td> </tr> <tr> <td width="150" bgcolor="silver">SIDEBAR</td> <td width="550" height="400" bgcolor="white"> <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:contentplaceholder> </td> </tr> <tr> <td colspan="2" align="center" height="20" bgcolor="gray"> FOOTER </td> </tr> </table> </div> </form> </body> </html>
Essentially, you have created a fairly typical layout with a header, sidebar, content, and footer region. For simplicity, this example just uses tables to create the layout. If you were to look in the Design tab in Visual Studio 2005, you should see something that resembles Figure 2.