Using ResolveClientUrl in markup

Onion Blog

Syndication

One of the useful features of working with server-side controls in ASP.NET is that you can use the '~' operator to create relative path references. For example, you can use a server-side Image control as follows:
 
<asp:Image runat="server" ImageUrl="~/images/mypic.gif" />
 
and it will resolve the imageurl reference to the root directory correctly. If this tag is referenced a level below the root, for example, it will resolve to src="../images/mypic.gif". You can even use this for some attributes in HtmlControls (including img and a):
 
<a href="~/default.aspx" runat="server" />
 
As long as the control is server-side and the attribute is one that ASP.NET resolves to evaluate the '~' symbol, it works great. This is espcially useful for user controls and master pages, where you don't know beforehand where the control or page will be evaluated, and the path may well change.
 
As soon as you get used to this feature, however, you find places where it doesn't work, which is frustrating. For example, you might think that you could set the background property of the body element by making it a server-side control:
 
<body runat="server" background="~/images/mypic.gif">... (note - doesn't work)
 
But that won't work, since the body element maps to the generic HtmlGenericControl which has no fields that will be resolve the '~' symbol.
The solution I typically use to deal with this, is to call Page.ResolveClientUrl directly in the markup:
 
<body background='<%= ResolveClientUrl("~/images/mypic.gif") %>' >...
 
This technique works well, although it does add some clutter to your page. What techniques have you used to deal with this issue?
 

Posted Feb 06 2006, 09:31 AM by fritz-onion
Filed under:

Comments

swildermuth@adoguy.com (Shawn Wildermuth) wrote Re: Using ResolveClientUrl in markup
on 02-06-2006 7:55 AM
This is the way I have always handled it. The case where ResolveClientUrl() doesn't seem to handle is when you want to resolve it to the full URL name. For example, if I run an app at http://adoguy.com/foo, ResolveClientUrl resolves '~/images/foo.jpg' to '/foo/images/foo.jpg'. What i'd prefer is to have an option to resolve it to 'http://adoguy.com/foo/iamges/foo.jpg' for use in non-html pages (e.g. RSS Feeds). I crafted a solution by tearing apart the request and fassening it to the new name, but it feels hacky and I am sure I am missing edge cases. I wish ASP.NET supported a solution for that.
Sergio Pereira wrote re: Using ResolveClientUrl in markup
on 02-06-2006 9:19 AM
I try as much as possible to put urls in CSS files, since they are interpreted relative to the .css location. If this is not possible, I resort to something similar to what you've done. Sometimes I take a step further and add a few protected methods to my base page class, like GetImageUrl("myicon.gif") and GetClientScriptURl("myhacks.js"), which return something like "/myApp/images/myicon.gif" and "/myapp/scripts/myhacks.js". Of course this assumes all those external resources are neatly organized in specific folders.
Phil Scott wrote re: Using ResolveClientUrl in markup
on 02-06-2006 9:40 AM
I've done something similiar, but I always use ResolveUrl, not ResolveClientUrl. I'm not sure if I'm doing something wrong, but I always run into problems with ResolveClientUrl when certain redirects get used.

For example, we have a custom 404 page (404.aspx) that sits in the root of the application. In IIS I set up 404 errors to go to this page. Everything works great unless I go to a non-asp.net handled page in a subfolder (e.g. madeup/nothere.htm). Then anything I used a tilda for in the master page gets jacked up. Taking a look at the source, all the URLs end up being relative links from the madeup folder, so it is looking "madeup/style.css" instead of "/style.css" If I use ResolveUrl I get a proper URL, so I have resorted to basically parsing the tilda by hand and making a call to ResolveUrl in the master page for this one situation.
haacked@gmail.com (Haacked) wrote Re: Using ResolveClientUrl in markup
on 02-06-2006 10:09 AM
I'll either write a base page (or a control you drop on any page) which iterates through controls looking for these specific cases that don't work and correct them. It's a bit of a brute force hack, but it handles the problem with MasterPages and dynamically loading user controls which don't deal well with the <%= ... %> syntax.
Diego Mijelshon wrote re: Using ResolveClientUrl in markup
on 02-06-2006 11:32 AM
I never had to do it, but I'd create an ExpressionBuilder that does the ResolveClientUrl for me, so I can write something like:

<body runat="server" background="<%$ URL:~/images/mypic.gif %>">

And if you implement EvaluateExpression, it even works in design time.
Eron Wright wrote re: Using ResolveClientUrl in markup
on 02-06-2006 12:08 PM
The ExpressionBuilder solution is a good one, but note that the expression is a constant and doesn't support parameterization. Expression builders are not particularly useful for the broader problem of shortening <%= %> codeblocks or binding-expressions (as an alternative to custom controls).
Diego Mijelshon wrote re: Using ResolveClientUrl in markup
on 02-07-2006 3:30 AM
Eron,

I think they ARE cleaner in a lot of cases.
Think, for example, of the AppSettingsExpressionBuilder. It's just a wrapper for ConfigurationManager.AppSettings[key] and TypeConverter.
Plus, you can support design time evaluation, which can be important in this case.
Fritz Onion wrote re: Using ResolveClientUrl in markup
on 02-08-2006 5:21 AM
Thanks for all the feedback, it's always good to see that I'm not suffering alone :) I like the idea of writing an URL expression builder...
Bilal Haidar [MVP] wrote re: Using ResolveClientUrl in markup
on 02-14-2006 12:07 PM
Hi Fritz:
Have you ever checked this:

http://www.codeproject.com/aspnet/UsingTheFileResolver.asp

Regards
Eugene Agafonov [ASP/ASP.NET MVP] wrote re: Using ResolveClientUrl in markup
on 03-05-2006 3:15 AM
Greetings!
I've implemented URL expression builder. But it seems to be quite useless.

It works for <body runat="server">, but evaluate expression isnt called in design time. It's called if i use it with server control like label, so the issue isnt in my expression builder.

Also it doesnt work in html tags. The only place i found it works is <link rel=Stylesheet type="text/css" href="<%$ Url:~/style/StyleSheet.css %>" />, but again, no design time.

So, If you could imagine any other use for this expression builder, please let me know :)
Dave Loukola wrote re: Using ResolveClientUrl in markup
on 05-01-2006 8:19 AM
Bobby DeRosa came up with a great solution for this problem that I use in my current apps.

http://www.csharper.net/blog/using_the_tilde__~__in_asp_net_everywhere___not_just_controls_.aspx

Check it out, I'm sure you'll like
Simon wrote re: Using ResolveClientUrl in markup
on 07-27-2006 8:14 AM
Hi, have you found a solution?

regards
Simon
Paul wrote re: Using ResolveClientUrl in markup
on 01-08-2007 12:31 PM
umm.... give it an id tag and a runat=server tag and assign the attribute in code. <%= %> normally means you are doing something wrong in asp.net....
gices wrote re: Using ResolveClientUrl in markup
on 05-03-2007 3:40 AM
How about when you're using <%# Eval() %> then Paul?
Mark wrote re: Using ResolveClientUrl in markup
on 05-27-2008 5:46 AM
Can anybody tell me where I can get detail infomation about <%#, <%$, etc. That would be high appreciated.
Adel wrote re: Using ResolveClientUrl in markup
on 07-02-2008 1:05 AM

You can even write the following:

<img src="<%Response.Write(Page.Request.ApplicationPath + "/images/MyImage.gif");%>" />

that's another solution

but the issue that you need to write this for each image in the sub folders pages!!!

Song White wrote re: Using ResolveClientUrl in markup
on 08-16-2008 4:38 PM

I am an asp.net beginner.  This is very helpful.  After several researches, I actually ended in using Page.ResolveURL, for a image file column from a table in my database.  It works fine:  

<img src ="<%#Page.ResolveUrl(CType(Container.DataItem, DataRowView).Item("Image_file"))%>" />

Saurabh wrote re: Using ResolveClientUrl in markup
on 09-18-2008 7:14 AM

I am having masterpage named mm.master in the root application and i have a content page which exists in a folder fldr but when I reference the masterpage from that contentpage I am not getting any error but the page is not having any effect means it is  not showing the Master Page in the background. Anybody who can help me?

Thanks,

Saurabh

Bruno wrote re: Using ResolveClientUrl in markup
on 04-22-2009 5:16 PM

Hi!

You could use <img src="<%= Request.ApplicationPath %>/Images/image.gif" /> . I find it clean. Bye!

shenghuo.cn wrote re: Using ResolveClientUrl in markup
on 05-20-2009 9:24 PM

i agree with you ! the Request.ApplicationPath is clean and fast to solve the problem

Add a Comment

(required)  
(optional)
(required)  
Remember Me?