Staying On The Correct Path

In a current task where I had to consolidate the structure of a website and organize the files better, I ran across
this interesting quirk.  When developing, we work in a virtual directory on our local machine, while on a real
server, it runs in the root directory.  This poses problems whenever we want to use relative paths to images,
stylesheets, etc.

The key to fixing this is the VirtualPathUtility, which has the logic in it to determine the root of the web
application and return a proper path.  I thought it would be easy to just use this object right in the markup
like:

        
<head runat="server">
    <title></title>
    <link id="cssLinkOutside" href='<%=System.Web.VirtualPathUtility.ToAbsolute("~/StyleSheet.css")%>' rel="stylesheet" type="text/css" />
</head>            
        
    

That didn’t work.  The rendered HTML turned out to be:

    
<link id="cssLinkOutside" href="&lt;%=System.Web.VirtualPathUtility.ToAbsolute("~/StyleSheet.css")%>" rel="stylesheet" type="text/css" />
    

Pretty literal.  The cause of this odd behavior is that the HEAD tag is set to runat=”server”.  If that
piece is taken out, the embedded code works well.  So if you need the HEAD to be a server control – like when
using themes – then what?  You can add code in the code-behind to do an attributes.add() on the LINK tag.  But having to add code in two places for such a simple need is just too much, especially when I was looking at
updating a couple dozen pages.

The workaround is kind of surprising: Wrap the tag that contains dynamic code in a placeholder.

        
<head runat="server">
    <title></title>
    <asp:PlaceHolder runat="server" id="holder">
        <link id="cssLinkInside" href='<%=System.Web.VirtualPathUtility.ToAbsolute("~/StyleSheet.css")%>' rel="stylesheet" type="text/css" />
    </asp:PlaceHolder>
</head>            
        
    

This renders the tag properly:

    
<link id="cssLinkInside" href='/WebTestbed/StyleSheet.css' rel="stylesheet" type="text/css" />