ASP.NET has improved dramatically with v2.0, to the point ofmaking ASP.NET v1.x look like a bit of a hack job. One of the greatimprovements covered in this entry is the addition of MasterPages.
Master Pages allows you to define a template layer (andcoupled back-end code) to be used on content pages using thatmaster page. For instance a master page might define all linkedscripts, CSS, and script blocks, along with a navigationheader and footer that exist on all pages on the site (or at leastthose pages using the master page). An ugly example sits asubdirectory away — at the rootpages for yafla, where the navigation header and footer existin a master page.
<%@ MasterLanguage=”C#” AutoEventWireup=”true”CodeFile=”MasterPage.master.cs” Inherits=”MasterPage”%>
<!DOCTYPE htmlPUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
<html xmlns=”http://www.w3.org/1999/xhtml” >
<title>My Master Page – This Title Will BeOverridden
By the Title ElementIn ContentPages</title>
<link rel=stylesheet type=”text/css”href=”stylesheet_in_all_pages.css” />
<h3>This is my universalheader!</h3>
<form id=”form1″ runat=”server”>
<h3>© 2015 RobotInc.</h3>
You can also define code for the various events in the master page,which will run on the pertinent content pages.
Content pages then define what will fill the content block (ormultiple content blocks as the case may be), and of courseimplement their own back-end code.
<%@ PageLanguage=”C#” MasterPageFile=”~/MasterPage.master”
Title=”This is my overridden title” %>
<asp:Content ID=”Content1″ContentPlaceHolderID=”ContentPlaceHolder1″ Runat=”Server”>
This is my content for this content page
Of course this isn’t the only way that this result could beachieved — I could derive from a page object that imperativelycreates all of the common elements, or I could use multiple usercontrols that defined the basics, but neither of those solutions,or similar workarounds, seem as elegant as master pages to me.There are equal or superior solutions in other platforms, howeverI’m sticking to the topic of ASP.NET in this entry so they areirrelevant.
The one hiccup I faced in the use of master pages was my desireto have meta keywords (which exist in the header) vary by page,despite the fact that the meta keyword is basically dead.I want the keywords to vary, similar to the way I candeclaratively override the title in content pages. Unfortunatelythis required some code workarounds, which in my case includedadding a public property on the master page, MetaKeywords, with adefault keyword list, which I then added to the header in thePreRender stage of the master page (the following exampleis simplified for demonstrations sake, however a realimplementation would scan the headers to ensure that the pertinentheader doesn’t already exist before adding it).
public string MetaKeywords = “default keywords”;
protected void Page_PreRender(objectsender, EventArgs e)
public static voidSetMetaValues(System.Web.UI.HtmlControls.HtmlHead head, stringname, string content)
HtmlMeta metaValue =null;
metaValue = newHtmlMeta();
Any content page could access its Master property to set theproperty, and the meta keywords would be appropriately set when thepage was rendered. By using the MasterTypedirective the Master property of the page automaticallyresolves to the proper type.
Unfortunate that a declarative mechanism wasn’t added forarbitrary header elements in the content pages.
The goal of master pages, of course, is to avoid the scourge ofcopy/paste coding: Unnecessarily having a single line of code inmultiple places is an evil in software development, yet it’s oftenthe easy, thoughtless solution, yielding volumes ofredundant code that invariably diverges and causes maintenanceproblems for years to come, reducing the quality and agility of thecodebase.
I despise copy/pasted code. It truly is a peeve of mine.
When analyzing the quality of code bases, one of the firstchecks I usually perform is to use one of the automated codeduplication checkers (available for most languages). There is aremarkable correlation between code duplication rates and codequality.
The benefit of master pages isn’t limited to a single mastertemplate, however, but instead you can actually layer multiplemaster pages. For instance on the yafla site the services categorypages use the Services master page, adding additional servicespecific back-end code and layout, while it uses the web site widemaster page. It mirrors the templated way in which many websitesare developed.
The downside of layered master pages is that the GUI teamapparently didn’t have time to build multiple level parsing intothe web designer — wherever you’re working on content pages thathave more than one level of master pages above them, you arelimited to the source view. To attempt otherwise yields a “Designview does not support creating or editing nested master pages. Tocreate or edit nested master pages, use the Source view.”Unfortunate, but not deadly.
As an aside, one of the big improvements with ASP.NET v2 isbetter support of per-page development, similar to classic ASP andcompetitors such as PHP. This solves one of the primary problemsmany had with ASP.NET, which is that they didn’t prefer to workwithin the “web site as a monolithic application” model thatASP.NET v1 pretty much enforced. Strangely the improvementsbringing these benefits has been met with little fanfare, and feware even aware of it. I do plan on doing a feature on itshortly.