1. Master Page Test Here's my 2nd Title!

<-- Back to Master Page Development
Continue to 2. Master Page Template Code-->
<---- Jump back to Master Page Development

Here's the id="divNoContentTag" that will have no content to fill the <contentplaceholder> tag. You see how .NET allows you to pass this content in the <contentplaceholder> directly from the master page to the result page. Normally a <asp:content> tag with the appropriate id would replace this in the content page. However, because there is no <asp:content> tag with this id, the default text appears.

Main Points

Master Page Code

Here's our first attempt at creating an ASP.NET master page.

Master Page (MasterPageTest.master)

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPageTest.master.cs" Inherits="MasterPageTest" %>
<!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" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="robots" content="all, index, follow" />
<meta name="Description" content="Welcome to Earthchronicle.com Beta! The behind the scenes testing for your online education resource for history." />
<meta name="Keywords" content="Earthchronicle, Earth, Chronicle, earth, chronicle, EarthChronicle.com, Beta, beta, Home, Page, Homepage, History, history, Historical, historical, Online, online, On-line, on, line, Education, Educational, education, educational, resource, Resource, test, testing, new features, next, version, generation, website" />
<title>
<asp:contentplaceholder id="cphPageTitle" runat="server" />
</title>
<link rel="shortcut icon" href="Images/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" media="all" title="ecstylesheet" href="CSS/ecMaster.css" />
</head>
<body>
<h1>
<asp:contentplaceholder id="cphPageHeading" runat="server">
Demo text that won't appear. It will be replaced by the page heading.
</asp:contentplaceholder>
</h1>
<asp:contentplaceholder id="cphNoContentTag" runat="server">
<p id="pMyParagraph">
Here's the id="divNoContentTag" that will have no Content for the ContentPlaceHolder. You see how .NET allows you to pass content from a master page to the result page, if there is no &lt;asp:content&gt; tag with that id in the content page.
</p>
</asp:contentplaceholder>

<asp:contentplaceholder id="cphEmptyContentTag" runat="server">
<p id="pMyParagraph">
Here's text that you won't see because there's a empty content tag that will wipe it out.
</p>
</asp:contentplaceholder>

<div>
<asp:contentplaceholder id="cphMainContent" runat="server" />
</div>
</body>
</html>

In this example we have one page, however, an ASP.NET master page is typically used as a structural template for an entire site. While it has it's own quirks, a master page's advantage is that it combines the best features of a control and a server side include (SSI). It stores a key piece of code that you will use over and over again in one place. Any changes made to the master page will instantly propagate to all pages which use it, just like SSI. However, where SSI constitutes a server hit, master pages only affect the server when it is built into the page the first time (or modified and the modifications are built the first time). Otherwise, the master pages are incorporated into the content pages during the build and download at the speed of a single static page, with minimal processing necessary from the server at the time the page is requested.

Also note the odd uses of contentplaceholder tags. The first example has id="cphNoContentTag" appears above at the top of the page. There is no corresponding <asp:content> tag in the content page. Therefore, the content added in the master page inside the <asp:contentplaceholder> tag has no competition and finds a spot on the page. This is the only case where content in the place holders appear on the page. Where the place holders have id="cphPageTitle" and id="cphEmptyContentTag" the content does not appear on the page. The content from the <asp:content> tags of the content page replace content listed in the contentplaceholder of the master page. Note that this holds true even for id="cphEmptyContentTag" where the content tag has no content at all, yet the content from the master page is not placed into this page.

Skip to Main Points

Content Page Code

Content Page (MasterPageTest.aspx)

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="MasterPageTest.aspx.cs" Inherits="MasterPageTest" MasterPageFile="~/MasterPageTest.master" %>
<asp:content ContentPlaceHolderId="cphPageTitle" runat="server">
Here's my Title!
</asp:content> <asp:content ContentPlaceHolderId="cphPageHeading" runat="server">
Here's my 2<sup>nd</sup> Title!
</asp:content>
<asp:content ContentPlaceHolderId="cphDoesntExist" runat="server">
Look all you want, but you won't find this anywhere on the webpage. A content tag must have a ContentPlaceHolder tag to go into. The server sees the master page when the content page pulls it in, and because the master page (see above code for the .master file) does not have an <asp:contentplaceholder id="cphDoesntExist" runat="server">, this content block causes an application error. If you are reading this, then this content tag has been removed and doesn't exist! :) Weirdly cool.
</asp:content>
<asp:content ContentPlaceHolderId="cphMainContent" runat="server">
...content...
</asp:content>
<asp:content ContentPlaceHolderId="cphEmptyContentTag" runat="server" />

Note how amazingly simple the content page is. It's a page directive, and a series of <asp:content> tags. Everything else is in the master page. The ContentPlaceHolderId attribute of the <asp:content> tag ties the the tag (and it's associated content) back to the master page's ContentPlaceHolder control whose id matches. It needs a lot of work, but this is a test. It certainly shows the potential of ASP.NET master pages.

OK, some more details. There are a couple of things that didn't even pan out well enough to show how they break. One, using the same Id for two ContentPlaceHolder controls in the master page seemed like a great way to insert the same piece of text into two places in the document. I was trying it with the main <h1> and the the <title> in the header. But the application error .NET threw when it tried to run with duplicate Ids was less desirable, so I threw in the towel with that one.

Unfairly, you will note that we were able to place content into a ContentPlaceHolder tag on the master page and display it even though there is no corresponding content tag in the content page. In fact, if there were, the content page would override what's available in the master page. However, If we add a content tag in the content page that has no corresponding ContentPlaceHolder tag on the master page, it not only doesn't display but creates an application error.

Also, as you would expect, a ContentPlaceHolder tag refused to fit into the content attribute of my meta keywords tag. The angle brackets (<>) and quotation marks of the ContentPlaceHolder wreak havoc with attribute value that we're trying to insert. It would have been handy to just dump it straight in, but that's not within the power of master pages. Looks like I'd have to use a database system to pull those keywords in a future update.

Skip to Main Points

Hacking the Controls

Setting up the page to display was not the easiest thing either. Master pages scramble id and name attributes in an attempt to prevent duplicate attribute names from different files from being pulled into the page where they suddenly cause errors. This is affecting the contact form below, note how the CSS styling is not taking effect because the ids have been altered and no longer match what's called in the CSS file.

Also the javascript for the navbar menus immediately stopped working. We tried moving the contact form and navbars to the master page thinking this was an issue with the scrambled ids. It was not, and it didn't solve the problem. However, the contact form and navbars are part of the standard portions of the page so they were left. This however, raises a serious issue that we still have to resolve. There are divs including the main footer div that are opened in the content page but closed in the master page. This is an unstable situation that needs to be resolved quickly.

The contact form image rollover is working fine. I added in the clock div, thinking that perhaps the navbar wasn't working because there were problems with the onload script. However, the clock function is called the same way and to my surprise it worked fine. To my even greater surprise, my navbar menus suddenly began working. I didn't understand why. When I removed the clock however, the menus stopped working. Now I could put the clock on every page... I could even do it with a master page after all. ;) However, I suspected that the clock function which was called first, was dying and preventing the navbar script which is called afterwards from being run. Since the clock and navbar scripts worked fine when the clock div was present and neither worked when it wasn't, I wrapped the entire clock function code in an if statement to feature sense for the clock box. The menus worked fine after that, whether there was a clock box or not.

Skip to Main Points
<-- Back to Master Page Development
Continue to 2. Master Page Template Code-->
<---- Jump back to Master Page Development