Custom Tags

One design pattern that I use over and over in various web projects is the use of custom tags that are embedded in markup and parsed on the server. ASP.NET makes this pattery very easy to use with its custom server controls feature.

Navigation Menu

This site has a DHTML navigation menu derived from HierMenus. I'm eventually going to replace it with my own menu system, but in the meantime I wanted to add some flexiblity to it. There is another site I've started hosting on this web host called SmartSam.com that uses this same menu, but I want the menu layout to be slightly different.

I had been using server-side includes to bring the menu structure into each page. The notion of putting real content into a comment has always felt really strange to me, but it worked well enough until now. What I wanted to do was include a different menu structure depending on which host the client was requesting from this server. I could have used SSI to execute a script, but this seemed like a great opportunity to use the custom-tag pattern again.

What I did was create a simple custom server control in a file named Menu.ascx. The code looks like the following:

<%@ Control Language="c#" %>
    <div class="nav">
        <a id="menuHome" href="/">Home</a>
<% if (Request.Url.Host.ToLower().EndsWith("smartsam.com")) { %>
        <a id="menuCourses" href="/courses.aspx" >Courses</a>
        <a id="menuLinks" href="/links.aspx" >Links</a>
<% } else { %>
        <a id="menuDotnet" href="/dotnet" >.NET</a>
        <a id="menuCode" href="/code" >WindowLib</a>
        <a id="menuDHTML" href="/dhtml" >DHTML</a>
        <a id="menuCSS" href="/style" >CSS</a>
        <a id="menuPictures" href="/pictures" >Pictures</a>
        <a id="menuLinks" href="/links.aspx" >Links</a>
        <a id="menuAbout" href="/about.aspx" >About</a>
<% } %>
    </div>

This is some simple code to output a block of links based on the host name the client is requesting. If the host is smartsam.com , then the first block of links is output; otherwise, the set of links in the else block is output.

To make this tag work I add a directive at the top of the page: <%@ Register TagPrefix="parkscom" TagName="Menu" Src="/Menu.ascx" %>. Then, wherever I want to the menu to appear I include a tag that reads <parkscom:Menu runat="server" />. The custom control outputs the appropriate markup for me. Easy!

Custom controls are even more powerful than that. When I get around to rewriting the menu system I will create a whole set of menu tags that will be compiled into a DLL. I am also considering creating additional tags to replace other server-side includes on this site.