First off, big thanks to Scott Allen for his coverage of master pages in ASP.NET 2.0. Scott nicely summarized some common gotchas that would’ve cost me time if I wasn’t aware of them.
One of the dilemmas master pages present is how to link to images, web pages, stylesheets, etc. Do you use a relative URL? Or an absolute one? Do you give, say, an image a runat="server" attribute and throw a tilde (~) in to have it resolved to the project root? There’s no easy answer.
HtmlHead Is Lacking
In 2.0 you may access the <head> element of a page server-side (provided you decorated it with runat="server"). The runtime treats it as an instance of the HtmlHead control.
What jumped out at me was its scarce list of useful methods and properties. Yes, there’s the much coveted Title attribute, but besides that… How do I register an external JavaScript file? Or a stylesheet? Or a meta tag. Granted, meta tags are for the most part only “hints” to browsers and therefore aren’t that useful, but still.
For example, I like to @import some of the stylesheets, and <link> the rest:
<style type='text/css' media='screen,projection'>
@import '/styles/layout.css';
</style>
<link rel='stylesheet' type='text/css'
media='print' href='/styles/print.css' />
You might want to do this to cater advanced styles to modern browsers, and older styles to legacy browsers. This way every browser gets what it can handle. Or, this way you may let owners of crappy browsers know it’s time to upgrade.
The HtmlHead control doesn’t have the luxury of doing much besides setting the page title and registering page-scope CSS rules. It’s a shame.
Some hacks, published online, suggest creating an HtmlLink control, setting its src and rel properties, adding it to the Controls collection, or resorting to even funkier logic with AddParsedSubObject(). All this to register a stylesheet and only a <link> one?! Maybe we should learn a thing or two from the Ruby on Rails folks. At least Rails was written by developers for developers.
My Hack
I wrote a base class for for my master pages. It simply exposes a property with the base URL of my project. If your project can switch between HTTP and HTTPS, you might want to add another private property for that instead of hardcoding “http://”.
When it comes to creating a new master page, I derive from my base class and plug the BaseURL property as follows:
<style type='text/css' media='screen,projection'>
@import '<%= BaseURL %>/styles/layout.css';
</style>
<link rel='stylesheet' type='text/css'
media='print' href='<%= BaseURL %>/styles/print.css' />
A master page is a good old combination of HTML markup and code-behind, which is why you can reference its properties.