On this page.... RSS 2.0 | Atom 1.0 | CDF
# Friday, March 31, 2006

In time, I hope to be able to look back on this day and think wow, was I ever that ignant?  Something that has plagued me and many others in ASP.NET 1.x has been resolved (no pun intended) in 2.0, viz. a static framework method to resolve an application-relative URL into a server-relative URL.  This is one of those problems that you feel like there must be a solution for, but maybe you just could never find it, or maybe you just didn't take the time because you created a solution that worked well enough.

In 1.x, on virtually every application I wrote, I ended up creating some utility method that would essentially do what the ~/ would do in a user control, which is equivalent to calling the ResolveUrl method.  The main idea, of course, is that we need a URL that is valid, regardless of the context, regardless of whether or not the application is being run on a development machine in a virtual directory or on a production server off the root.  Or maybe we just wanted to make it easy to change the virtual directory name--you know how fickle those users can be when it comes to what they want to see in the address bar! :)

So what did you do in 1.x?  Specifically when you didn't have a readily-available control to call ResolveUrl on?  If you're anything like me, DotNetNuke, or sundry others, you probably made some utility function that would squish the application path in front of the URL using the Request.ApplicationPath, if you could, or if you were really knowledgeable, the HttpRuntime.AppDomainAppVirtualPath property.  (Shh, don't tell anyone.. apparently, I'm not that knowledgeable as I just had this pointed out to me by David Ebbo; I usually hacked that one as well, storing it in my Global class by ripping it off of HttpRequest or worse, specified it in the web.config... oog).

Well, even if you do get the application path, you still have to write a function to munge it with the relative URL to come up with what I call the server-relative URL (i.e., an URL that starts with /).  Good grief!  Couldn't they have a function to do this that is static (doesn't require a valid request context)!?

Never fear, in 2.0, we have a neat new utility class called VirtualPathUtility!  You can read through the docs to figure out all the neat-o features, but the only one I particularly care about is ToAbsolute.  This one is, as far as I can make out, the functional equivalent of ResolveUrl, so now I can resolve server-relative URLs from app-relative ones without needing a valid request context and without writing my own functoid for it.  Woohoo!  Note: I say "server-relative" because the URL is relative to the server root.  For some reason, the MS folks call it "Absolute."  To me, absolute would include the full URL, including server.  I'm sure they had a good reason for it...

So that's it.  No more messing about with all that garbage.  Just declare all of your URLs using ~/, and call VirtualPathUtility.ToAbsolute to get a URL that should be valid regardless of your deployment environment.  Too cool! 

Edit: Forgot to give credit to David Ebbo on the Web Platforms and Tools Team at Microsoft for pointing out this new utility class to me.  Thanks, David!

Friday, March 31, 2006 9:50:42 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [2]  | 
Monday, April 3, 2006 8:10:49 PM (Eastern Daylight Time, UTC-04:00)
There is a difficulty with using an ASP.NET utility method to resolve URLs. In order to use the utility, you must somehow "pass" the unresolved path (~/whatever) to the utility in order to discover its root-relative equivalent (/appName/whatever). The difficulty is that not all paths are easy to pick out in order to be pased to the utility. Consider a url(/image.gif) address that is within a style definition.

I elected not to solve this difficulty, but to skip it altogether. Rather than resolving the URLs one by one with a utility method, I don't touch them at all. Then, once the entire page has rendered, I use a Filter to apply a few regular-expressions-based find and replace operations on the final HTML. Any root-relative paths it finds (/example) will have the name of the virtual path added (/appName/example). That way, I can simply place a new piece of HTML on my webpage, and not have to worry if it includes a root-relative URL. The Filter will fix it later.

I am not suggesting the Filter technique is better. I am saying only that it is an alternative. This alternative approach is documented on my website, at www.edition3.com/articles/root-relative-paths.
Monday, April 3, 2006 8:39:44 PM (Eastern Daylight Time, UTC-04:00)
That's an ingenious approach, and I certainly wouldn't recommend using ToAbsolute on every URL. CSS, in particular, is relative to the CSS file, so it is usually best to use URLs relative to the CSS files for those. The ToAbsolute is best in situations where you might otherwise be processing the URL on the server anyways but don't have access to a control context to use ResolveUrl. It's probably more useful for utilities, modules, and the like, but for some reason, I seem to do a fair number of those. :)
Comments are closed.

Disclaimer
The opinions expressed herein are solely my own personal opinions, founded or unfounded, rational or not, and you can quote me on that.

Thanks to the good folks at dasBlog!

Copyright © 2019 J. Ambrose Little