Working on an ASP.NET MVC application and needed the ability to resolve a URL from a partial view. For example, I have an image I want to display, but I need to resolve the virtual path (say, ~/Content/Images/New.png) into a relative path that the browser can use, such as ../../Content/Images/New.png or /MyAppName/Content/Images/New.png.
A standard view derives from the System.Web.UI.Page class, meaning you have access to the ResolveUrl and ResolveClientUrl methods. Consequently, you can write markup/code like the following:
<img src='=<%=Page.ResolveClientUrl("~/Content/Images/New.png")%>' />
The problem is that the above code does not work as expected in a partial view. What's a little confusing is that while the above code compiles and the page, when visited through a browser, renders, the call to Page.ResolveClientUrl returns precisely what you pass in, ~/Content/Images/New.png, in this instance. The browser doesn't know what to do with ~, it presumes it's part of the URL, so it sends the request to the server for the image with the ~ in the URL, which results in a broken image.
I did a bit of searching online and found this handy tip from Stephen Walther - Using ResolveUrl in an HTML Helper. In a nutshell, Stephen shows how to create an extension method for the HtmlHelper class that uses the UrlHelper class to resolve a URL. Specifically, Stephen shows how to add an Image extension method to HtmlHelper. I incorporated Stephen's code into my codebase and also created a more generic extension method, which I named ResolveUrl.
public static MvcHtmlString ResolveUrl(this HtmlHelper htmlHelper, string url)
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
With this method in place you can resolve a URL in a partial view like so:
<img src='<%=Html.ResolveUrl("~/Content/Images/New.png")%>' />
Or you could use Stephen's Html.Image extension method (although my more generic Html.ResolveUrl method could be used in non-image related scenarios where you needed to get a relative URL from a virtual one in a partial view). Thanks for the helpful tip, Stephen!