Using the Tilde ( ~ ) in ASP.NET Everywhere - Not Just Controls!
posted on Wednesday, November 09, 2005 by bobby @ 7:05 pm
If you are not familiar with tilde usage in ASP.NET, then you are sooooo missing out. Many times our development environment is totally different than a production server. We may test our application using a virtual directory on our development machine, but may publish to a dedicated root site.

So when you add an image or a link, you must always be aware of the type of path you provide - relative, absolute, etc. Well, one of the best little tricks of ASP.NET is the tilde (~). This is essentially a shortcut for the HttpRuntime.AppDomainAppVirtualPath property, which refers to the virtual application root, not the root of the web server.

So now that everyone knows why the tilde kicks-ayass, let me tell you why it doesn't... because it's only available for usage when setting path propeties of certain server controls and web.config settings. Examples of this would be:

System.Web.UI.WebControls.Image.ImageUrl

But I want to be able to use the tilde everywhere - in markup, in regular HTML, in XSL even. I want to use it as if it was part of HTML. Well now you can. The following code takes what would normally be rendered to the client, replaces any paths w/ a leading tilde to a real resolved path, and then writes the rendered output to the client.

Note - there is a minor performance hit by reading the output into a memory stream, parsing it, and then re-writing it. Use this wisely and monitor it closely to make sure you aren't taking a significant hit.

Copy code to clipboard in IE or select code for Firefox
protected override void Render(HtmlTextWriter writer)
{
    MemoryStream ms = new MemoryStream();
    StreamWriter sw = new StreamWriter(ms);
    HtmlTextWriter htw = new HtmlTextWriter(sw);

    base.Render(htw);
    htw.Flush();
    ms.Position = 0;

    TextReader tr = new StreamReader(ms);
    string output = tr.ReadToEnd();
    string newOutput = ReplaceWithAppPath(output);
    writer.Write(newOutput);
    
    htw.Close();
    sw.Close();
    ms.Close();
}

public static string ReplaceWithAppPath(string str)
{
    string appPath = HttpContext.Current.Request.ApplicationPath;

    //Ensure the app path ends w/ a slash
    if(!appPath.EndsWith("/"))
        appPath += "/";

    return str.Replace("~/", appPath);
}


Good dealio.

CommentsComments
posted on Wednesday, November 30, 2005  by Anonymous @ 5:20 AM

Having trouble getting this work in the new ASP.Net 2.0 model. ~ references the current directory no matter what.
posted on Wednesday, November 30, 2005  by bobby @ 7:31 AM

I'm not sure I understand your problem. This should work fine in both ASP.NET 1.1 and ASP.NET 2.0. This site is 2.0 and utilizes this trick w/ no issues.

Perhaps you could elaborate - send me an email and I'd be happy to help.
posted on Tuesday, January 24, 2006  by NotDyn @ 5:40 AM

I just discovered your Render magic. It's pretty sweet, it replaces a couple of dozen of lines of code I did in my 1.1 Framework days.

Now for bonus points. I am using an HTC to properly display PNGs for IE users. The HTC (and .css that specifies the behavior) need the same kind of path magic that .aspx files do. I'm using ASP.NET 2.0. What do you think?
posted on Tuesday, January 24, 2006  by bobby @ 7:25 AM

Hey,

Not sure if this will work for HTC files, but have a look at this article

Using Virtual Application Paths ( ~ ) in Any File!
posted on Tuesday, February 14, 2006  by Anonymous @ 10:58 PM

Why does your code remove any trailing '/' from the appPath, and then append a '/' to the appPath if the appPath doesn't end with a '/'.
Is this to handle cases when the appPath ends with '//' when would such a case occur?
posted on Wednesday, February 15, 2006  by bobby @ 12:11 AM

I think it was supposed to be one or the other (not both conditionals). Thanks for pointing this out. Code updated.
posted on Friday, April 07, 2006  by Bruno @ 2:34 AM

Hi,
I get the followig error:
Invalid file name for monitoring: 'c:\inetpub\wwwroot\~'. File names for monitoring must have absolute paths, and no wildcards.
when i use it like this:

<img src="~/images/interface/nptquickstarts_r1_c1.jpg.ashx" />

Any way to solve this on .net 1.1?

Thanks
posted on Monday, July 31, 2006  by opello @ 11:47 AM

Wouldn't a compiled regular expression be faster than the String.Replace()?

Just an idea, I've not really researched it extensively ...
posted on Tuesday, April 03, 2007  by poLen @ 1:13 PM

that may sound silly but i wonder where to put these codes. in every single .cs file?..
posted on Tuesday, April 03, 2007  by bobby @ 1:49 PM

You could if you wanted. Ideally, you'd have a base page class that all pages inherit from.
posted on Wednesday, November 21, 2007  by opto @ 3:48 AM

This is sooo sweet :)

Thank you!
posted on Tuesday, September 30, 2008  by Anonymous @ 7:07 AM

Hi,

does this also work with external css files? Are the ~'s in these files also replaced?
posted on Thursday, November 20, 2008  by Al @ 2:34 AM

If I do not inherit from a base page - what about putting the code into the master page? Is it total overkill?
posted on Sunday, February 08, 2009  by Anonymous @ 10:14 AM

Thanks. This is really useful... Great job!
posted on Wednesday, February 11, 2009  by Wes @ 1:12 PM

Very nice tip, thanks :-)
posted on Thursday, June 04, 2009  by Mahmud Khaled @ 8:37 AM

cheers mate!! nice tip.
posted on Tuesday, July 14, 2009  by satish faridabad @ 2:38 AM

thanks ~ its work in IE and Mozilla


New Post Notification

Search Posts

Recent Posts


About Meeself
People call me Bobby DeRosa
I live somewhere in San Diego, CA
MCSD, MCAD, MCP

This theme was adapted from fUnique by fahlstad        Icons by FamFamFam        XHTML 1.0 Strict; tuned for Mozilla-powered browsers

Admin Login Administrator Login
Invalid login attempts are logged.
  Username:
  Password: