Well designed websites do not consist of completely independent pages. They give the feeling of a continuously running application. Good design practice is to offer the site visitors similar interface and user experience no matter where they are on the website. The most common shared interface between different pages of the same website is about the header and footer.
This design is not only good for site visitors but also for site developers. This way, they don’t need to make the same change over and over again on every page that contains a common section but edit just the section and reuse it on every page.
The main solution that ASP .NET offers is called Master page. Master pages are files containing HTML tags, ASP .NET controls and possibly some code. Their file extension is .master. Master pages cannot be seen directly in the browser since they are just fragments of a page – they always need to be used by the content pages. Let’s see how a siple master page looks like:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="SiteTemplate.master.cs" Inherits="SiteTemplate" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="myForm" runat="server"> <img src="sun.jpg" /><br /> <asp:ContentPlaceHolder id="cp1" runat="server"> </asp:ContentPlaceHolder> <strong>This is some text.</strong> </form> </body> </html>
Normal content pages are connected to the master pages by the following directive placed at the top of the content page:
<%@ Page Language="C#" MasterPageFile="~/SiteTemplate.master" AutoEventWireup="true" CodeFile="SimpleContentPage.aspx.cs" Inherits="SimpleContentPage" Title="This is a content page" %> <asp:Content ID="ct1" ContentPlaceHolderID="cp1" runat="Server"> <br /> This is the content of the page <br /> </asp:Content>
Although content pages are not meant to overwrite (respectively, to include) the elements of the master page and the master page is meant to contain the <head> element, in the example above you can see that the page title was changed by an attribute in the Page directive. This is a useful workaround that ASP .NET offers so different content pages can have different titles and not the default one provided by the master page.
Both examples contain some content-related controls. This is how ASP .NET knows where to put the page-specific content inside the master page structure.
In the master page, the asp:ContentPlaceHolder control shows the place where the content will appear.
In the content pages, the asp:Content control shows which content will be displayed inside a master page ContentPlaceHolder with the same id as the value of the attribute ContentPlaceHolderID.
Master pages can contain multiple ContentPlaceHolders and each of them will be filled with data from a Content control with corresponding id.
The asp:ContentPlaceHolder can contain some elements too:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="SiteTemplate.master.cs" Inherits="SiteTemplate" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="myForm" runat="server"> <img src="sun.jpg" /><br /> <asp:ContentPlaceHolder id="cp1" runat="server"> <h1>This is default content</h1> </asp:ContentPlaceHolder> <strong>This is some text.</strong> </form> </body> </html>
Whenever a ContentPlaceHolder doesn’t find any corresponding Content control to fill data from, it will display on the website the default content. If a corresponding Content is found, the default content will be replaced with the elements from the Content control.
Nested Master Pages
Master pages can use another master page. The directive of a child master page will look like this:
<%@ Master Language="C#" MasterPageFile="~/ParentMaster.master" AutoEventWireup="true" CodeFile="ChildMaster.master.cs" Inherits="ChildMaster" %>
This is sometimes useful when developers need a universal section for the whole website and a few different sections depending on the webpage. For example, the header can be the same across the entire website, but different pages may need different navigations. Some of them will have horizontal navigation while others will have a vertical one. In this case, the header is put inside the parent master page and the navigations are put inside two different child master pages both using the parent.
This approach might be risky as it can add extra complexity to the master page hierarchy or create confusion about the appropriate place of each section and element.