Dynamically Varying Master Pages By Browser Type
As I was sitting in the audience, I thought about how easy it would be to do this instead with ASP.NET 2.0 and Master Pages. Instead of having to use multiple SSI include files to pull in content all over a page (for example: a SSI include for the header that lays out the top level table, then a separate SSI for the footer, and maybe a few more for other content regions), you will instead be able to just create a master page with replaceable regions.
For example, here is a simple psuedo-sample demonstrating a master page with two replaceable regions:
ArticleMaster.master
<html>
<head>
Link to some CSS stylesheet
</head>
<body>
Some Header content (including tables for layout)
<form runat=server>
<asp:contentplaceholder id="ArticleTitle" runat="server"/>
<table>
<tr>
<td>
<asp:contentplaceholder id="ArticleContent" runat="server"/>
</td>
</table>
</form>
</body>
</html>
As everyone who has looked at ASP.NET 2.0 knows, you can then easily build multiple .aspx pages that are based on this master:
Article1.aspx:
<%@ Page MasterPageFile="ArticleMaster.master" %>
<asp:content id="ArticleTitle" runat="server">
Dynamically Varying Master Pages By Browser Type
</asp:content>
<asp:content id="ArticleContent" runat="server">
My article content...
</asp:content>
ASP.NET 2.0 automatically compiles the two files the first time they are hit (you can also do this before a browser hits the site by using the precompile utility). As such, the files are never parsed on subsequent requests and execute lightening fast.
Programatically Varying Master Pages
What is less well known is the fact that Master Pages -- in addition to being set statically like above -- can be dynamically switched on the fly as well. As such, you could have multiple versions of a master page -- including ones optimized for different devices -- on your site. For example:
ArticleMaster.master
ArticleMaster_IE.master
ArticleMaster_FireFox.master
ArticleMaster_Safari.master
ArticleMaster_Opera.master
A page developer could then write code within the Page's PreInit event to update the Master template used for the page depending on what browser device hits it. For example:
void Page_PreInit(Object sender, EventArgs e) {
if (Request.Browser.IsBrowser("IE")) {
this.MasterPageFile = "ArticleMaster_IE.master";
}
else if (Request.Browser.IsBrowser("Mozilla")) {
this.MasterPageFile = "ArticleMaster_FireFox.master";
}
else {
this.MasterPageFile = "ArticleMaster.master";
}
}
Declaratively Varying Master Pages
A neat trick, though, is to use the new declarative device filter syntax in ASP.NET 2.0 to switch the master declaratively without having to write code at all. Device filters are prefixes that can be used on all control properties and look like this:
<asp:button id="Button1"
ie:text="Push me you IE user"
mozilla:text="Push me you FireFox user"
text="Push me you -- you are running neigher IE or Safari..."
runat="server"/>
The ASP.NET parser will automatically generate a switch statement when compiling markup like this, and insert logic to set the "text" property only once depending on the client that hits the page. Prefix names can be defined within the ASP.NET browser capabilities system, and you can easily add your own entries as new devices come out. Note that we goofed and didn't have a FireFox entry defined for Beta1 -- we will be adding that though for Beta2. In the meantime you can use the built-in "Mozilla" one (which will fire when FireFox hits the site), or just add a new FireFox entry yourself.
As I alluded to above, in addition to setting control properties via declarative filters you can also set <%@ Page %> directive values. This means that you can declaratively vary the master page used on file by doing something like this with the article page:
<%@ Page MasterPageFile="~/ArticleMaster.master"
ie:MasterPageFile="~/ArticleMaster_IE.master"
mozilla:MasterPageFile="~/ArticleMaster_FireFox.master" %>
<asp:content id="ArticleTitle" runat="server">
Dynamically Varying Master Pages By Browser Type
</asp:content>
<asp:content id="ArticleContent" runat="server">
My article content...
</asp:content>
This will execute the master page with an optimized IE or FireFox master template if hit by one of those broswers. Failing that, it will fall back to render a browser neutral version.
Designers can then edit and create the master templates just like they do regular HTML (leaving replaceable regions for the parts to fill in). Because the template can live in one file, and not need to be separated out in dozens of smaller SSI include snippets, this should be significantly easier to-do then before.
I think this should provide a nice clean solution...