ResolveUrl() without Page
ASP.NET's Control class provides the handy ResolveUrl method that lets you easily use and parse relative URLs. ResolveUrl fixes up urls that start with ~ and puts the applications relative root path in its place. So if I'm in:
/wwstore/admin/Configuration.aspx
and I reference ~/images/someimage.gif ResolveUrl will return /wwstore/images/SomeImage.gif to me. This is much better than hardcoding /wwstore/images/someimage.gif or even using a relative path like ../images/someimage.gif. Using the ~ syntax makes the app much more resilient to pages or controls moving inside of the application. Most controls that have URL properties also use ResolveUrl so you can specify URLs on control properties using the same relative syntax.
Sometimes however, I find myself in some generic piece of Web code where I don't have access to the Page or a Control to actually use Control.ResolveUrl. For example, I was working on my Resource Provider recently and one of the options of the provider is to specify the resource administration for URL using - you guessed it ~ style relative path syntax. Deep inside the provider code I have no access to a page object - in fact the code may never actually hit a page handler at all but a custom HttpHandler instead.
So this issue comes up from time to time, and it's useful to have a more generic ResolveUrl method. I thought that there was some method somewhere buried deep on HttpContext that could perform this fix up but I can't for the life of me find it. In the meantime I've been using the following code:
/// <summary>
/// Returns a site relative HTTP path from a partial path starting out with a ~.
/// Same syntax that ASP.Net internally supports but this method can be used
/// outside of the Page framework.
///
/// Works like Control.ResolveUrl including support for ~ syntax
/// but returns an absolute URL.
/// </summary>
/// <param name="originalUrl">Any Url including those starting with ~</param>
/// <returns>relative url</returns>
public static string ResolveUrl(string originalUrl)
{if (originalUrl == null)
return null;
// *** Absolute path - just returnif (originalUrl.IndexOf("://") != -1)
return originalUrl; // *** Fix up image path for ~ root app dir directoryif (originalUrl.StartsWith("~"))
{string newUrl = "";
if (HttpContext.Current != null)
newUrl = HttpContext.Current.Request.ApplicationPath +originalUrl.Substring(1).Replace("//", "/");
else // *** Not context: assume current directory is the base directorythrow new ArgumentException("Invalid URL: Relative URL not allowed.");
// *** Just to be sure fix up any double slashes return newUrl;}
return originalUrl;}
You call it just like you would Control.ResolveUrl() and it will return an Application relative path.
Another related scenario is to resolve URLs into fully qualified absolute URLs. For example, in several applications I have callback URLs that get passed to various services like PayPal and Trackback services, that are supposed to call back your application. These pages need to get a fully qualified URL so they can find your page on the Web. Another scenario where I found this necessary is when you need to switch URLs into ssl as part of your application. For example, in my store you enter as a non-SSL URL until you hit the order pages at which point the page switches to SSL and you have to provide a fully qualified URL to do so.
/// <summary>
/// This method returns a fully qualified absolute server Url which includes
/// the protocol, server, port in addition to the server relative Url.
///
/// Works like Control.ResolveUrl including support for ~ syntax
/// but returns an absolute URL.
/// </summary>
/// <param name="ServerUrl">Any Url, either App relative or fully qualified</param>
/// <param name="forceHttps">if true forces the url to use https</param>
/// <returns></returns>
public static string ResolveServerUrl(string serverUrl, bool forceHttps)
{ // *** Is it already an absolute Url?if (serverUrl.IndexOf("://") > -1)
return serverUrl; // *** Start by fixing up the Url an Application relative Url string newUrl = ResolveUrl(serverUrl);Uri originalUri = HttpContext.Current.Request.Url;
newUrl = (forceHttps ? "https" : originalUri.Scheme) + "://" + originalUri.Authority + newUrl; return newUrl;}
/// <summary>
/// This method returns a fully qualified absolute server Url which includes
/// the protocol, server, port in addition to the server relative Url.
///
/// It work like Page.ResolveUrl, but adds these to the beginning.
/// This method is useful for generating Urls for AJAX methods
/// </summary>
/// <param name="ServerUrl">Any Url, either App relative or fully qualified</param>
/// <returns></returns>
public static string ResolveServerUrl(string serverUrl)
{return ResolveServerUrl(serverUrl, false);
}
So the following applies:
// returns https://www.west-wind.com/wwStore/test.aspx Response.Write( wwWebUtils.ResolveServerUrl("~/Test.aspx",true));
This is one of those things that's not needed frequently but when you do it's a pain to try and start remembering exactly how to retrieve these values. For me this happens often enough that I'll keep this in my toolbox.
Other Posts you might also like
The Voices of Reason
# re: ResolveUrl() without Page
I believe you were looking for the VirtualPathUtility class.
http://msdn2.microsoft.com/en-us/library/system.web.virtualpathutility_methods.aspx
By the way, I *always* have to enter the validation code twice when commenting here...
# re: ResolveUrl() without Page
We are so often on the same wavelength. I too just enabled a bunch of my own controls to use the virtual path character ("~").
As Sergio and Josh mentioned, the VirtualPathUtility works great for this. The statement I use is:
newUrl = VirtualPathUtility.ToAbsolute(sourceUrl);
# re: ResolveUrl() without Page
Anyway, it looks that this solves only a part of the issue - namely ~/ prefixed paths. Which is fine since that is the most common scenario and it just allows reducing the code in the ResolveUrl method a bit.
I still like the idea though of being able to handle both fully qualified absolute paths (ie. with http://) as well as relative paths without ~/ all from one place. For example in the scenario of the Url for a configuration page it's possible that the URL lives in a completely separate application or even server...
So I guess I'll hang on to the above with a small modifcation for the ~ operation.
public static string ResolveUrl(string originalUrl) { if (originalUrl == null) return null; // *** Absolute path - just return if (originalUrl.IndexOf("://") != -1) return originalUrl; // *** Fix up image path for ~ root app dir directory if (originalUrl.StartsWith("~")) return VirtualPathUtility.ToAbsolute(originalUrl); return originalUrl; }
The full server URL version is still required though.
Thanks all!
# re: ResolveUrl() without Page
"~/html/test.aspx?url=http://www.testuri.org/"
I cannot imagine any circumstance where the URL starts with "~" and you wouldn't want to translate it, even if it contains "://".
...constantly refactoring... ;-)
# re: ResolveUrl() without Page
This is actually incredibly useful for dynamically created for stylesheets and JavaScript which are created/referenced on the code-side.
One of the problems I have in .NET is that you can reference ~ in most tags like hyperlinks and css, but not JavaScript. I've no idea why that is.
This method is particularly good for me, so that I can have websites in virtual directories which, when published, are the root.
The downside of all this is that non-.NET files (*.js, *.css, et al) are not handled the same way. For example, the url attribute in CSS. If it's an absolute url in that, it would need to be handled in a http handler.
# re: ResolveUrl() without Page
public static string ResolveUrl(string originalUrl) { if (!string.IsNullOrEmpty(originalUrl) && '~' == originalUrl[0]) { int index = originalUrl.IndexOf('?'); string queryString = (-1 == index) ? null : originalUrl.Substring(index); if (-1 != index) originalUrl = originalUrl.Substring(0, index); originalUrl = VirtualPathUtility.ToAbsolute(originalUrl) + queryString; } return originalUrl; }
To resolve the full URL, I tend to use the Uri and UriBuilder classes:
public static string ResolveServerUrl(string serverUrl, bool forceHttps) { Uri result = HttpContext.Current.Request.Url; if (!string.IsNullOrEmpty(serverUrl)) { serverUrl = ResolveUrl(serverUrl); result = new Uri(result, serverUrl); } if (forceHttps && !string.Equals(result, Uri.UriSchemeHttps)) { UriBuilder builder = new UriBuilder(result); builder.Scheme = Uri.UriSchemeHttps; builder.Port = 443; result = builder.Uri; } return result.ToString(); }
# re: ResolveUrl() without Page
var url = '<%= ResolveUrl("~/images/wait.gif") %>';
but that obviously only works for Urls that are server static.
@Richard - thanks for the querystring reminder. Very good point in fact. The more generic the better <s>...
# re: ResolveUrl() without Page
# re: ResolveUrl() without Page
# re: ResolveUrl() without Page
if (HttpContext.Current != null) newUrl = HttpContext.Current.Request.ApplicationPath + originalUrl.Substring(1).Replace("//", "/");
Gary Davis
# re: ResolveUrl() without Page
which is the best version of those methods ?? mister Richard Deeming's version ???
It would be interesting if the right (best) version is R.Deeming's code, you can update it in this post.
Thanks in advance, best regards.
# re: ResolveUrl() without Page
Uri uriFull = new Uri(uriReferer, urlRelative);
I've used this code in a console-based utility I'm writing to follow the links in my web app, and it's yet to do the wrong thing. If the relative URL starts with "..", the referer obviously has to be an appropriate path. If it's not, you may have found a bad link in your app (like something hard-coded as "../whatever" when "~/path/whatever" should be used).
What I'd really like now is a way to force Page.ResolveUrl to always return its URLs as an app-absolute path (i.e. always with a leading '/'). It frequently will return relative paths like "../images/mypic.gif", and I'd prefer to see "/myapp/images/mypic.gif"). Obviously, I can't hit everyplace in the code to make a change to effect this, so it would be great if there were a Web.config setting or something like that to get that behavior.
FWIW...
Donnie
# re: ResolveUrl() without Page
Actually ResolveUrl should always return absolute url (with leading "/") and should return ResolveClientUrl returns relative url.
Talking about VirtualPathUtility.ToAbsolute() and uri with query string. Another available option is to use HttpRuntime.AppDomainAppVirtualPath (http://dotnettipoftheday.org/tips/HttpRuntime.AppDomainAppVirtualPath.aspx)
# re: ResolveUrl() without Page
I found Deeming's replacement code to introduce some inconsistencies such as rewriting url's that are already absolute to using https, which I felt was outside the scope of this classes responsibility. I liked Strahl's assumption that if a Url is already absolute, do nothing with it.
Additionally, Strahls's original code for forcing https looked like it might fail if called on a server using a non-standard port, because the originalUri.Authority docs state that this uses DNS or IP *and* the port name for a server. i.e. https://somemachine:8080/path/file.aspx. I didn't test this assertion, but instead I opted to use the UriBuilder which should do the right thing.
PS from a style perspective, I altered Deeming's code to stop overwriting variables that were passed in because I find it quite hard to follow otherwise.
/// <summary> /// Returns a site relative HTTP path from a partial path starting out with a ~. /// Same syntax that ASP.Net internally supports but this method can be used /// outside of the Page framework. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="originalUrl">Any Url including those starting with ~</param> /// <returns>relative url</returns> public static string ResolveUrl(string originalUrl) { if (string.IsNullOrEmpty(originalUrl)) return originalUrl; // *** Absolute path - just return if (originalUrl.IndexOf("://") != -1) return originalUrl; // *** Fix up path for ~ root app dir directory if (originalUrl.StartsWith("~")) { // VirtualPathUtility blows up if there is a query string, so we // have to account for this. int queryStringStartIndex = originalUrl.IndexOf('?'); if (queryStringStartIndex != -1) { string queryString = originalUrl.Substring(queryStringStartIndex); string baseUrl = originalUrl.Substring(0, queryStringStartIndex); return VirtualPathUtility.ToAbsolute(baseUrl) + queryString; } else { return VirtualPathUtility.ToAbsolute(originalUrl); } } return originalUrl; } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <param name="forceHttps">if true forces the url to use https</param> /// <returns></returns> public static string ResolveServerUrl(string serverUrl, bool forceHttps) { if (string.IsNullOrEmpty(serverUrl)) return serverUrl; // *** Is it already an absolute Url? if (serverUrl.IndexOf("://") > -1) return serverUrl; string newServerUrl = ResolveUrl(serverUrl); Uri result = new Uri(HttpContext.Current.Request.Url, newServerUrl); if (forceHttps) { UriBuilder builder = new UriBuilder(result); builder.Scheme = Uri.UriSchemeHttps; builder.Port = 443; result = builder.Uri; } return result.ToString(); } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// It work like Page.ResolveUrl, but adds these to the beginning. /// This method is useful for generating Urls for AJAX methods /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <returns></returns> public static string ResolveServerUrl(string serverUrl) { return ResolveServerUrl(serverUrl, false); }
# re: ResolveUrl() without Page
Small refactorings to make it more readable. You could always collapse the initial if's into one, but it's all the same (and would likely be optimised that way)
Also, here's the table of results:
~/SomePage.aspx /WebSite/SomePage.aspx
~/SomePage.aspx http://localhost/WebSite/SomePage.aspx
~/SomePage.aspx https://localhost/WebSite/SomePage.aspx
~/With/Path.aspx /WebSite/With/Path.aspx
~/With/Path.aspx http://localhost/WebSite/With/Path.aspx
~/With/Path.aspx https://localhost/WebSite/With/Path.aspx
~/WithQuery.aspx?id=1234&page=2 /WebSite/WithQuery.aspx?id=1234&page=2
~/WithQuery.aspx?id=1234&page=2 http://localhost/WebSite/WithQuery.aspx?id=1234&page=2
~/WithQuery.aspx?id=1234&page=2 https://localhost/WebSite/WithQuery.aspx?id=1234&page=2
http://absolute.net/page.aspx http://absolute.net/page.aspx
http://absolute.net/page.aspx http://absolute.net/page.aspx
http://absolute.net/page.aspx http://absolute.net/page.aspx
/Already/Root/Relative.aspx /Already/Root/Relative.aspx
/Already/Root/Relative.aspx http://localhost/Already/Root/Relative.aspx
/Already/Root/Relative.aspx https://localhost/Already/Root/Relative.aspx
and the new code:
/// <summary> /// Returns a site relative HTTP path from a partial path starting out with a ~. /// Same syntax that ASP.Net internally supports but this method can be used /// outside of the Page framework. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="originalUrl">Any Url including those starting with ~</param> /// <returns>relative url</returns> public static string ResolveUrl(string originalUrl) { if (string.IsNullOrEmpty(originalUrl)) return originalUrl; // *** Absolute path - just return if (originalUrl.IndexOf("://") != -1) return originalUrl; // *** We don't start with the '~' -> we don't process the Url if (!originalUrl.StartsWith("~")) return originalUrl; // *** Fix up path for ~ root app dir directory // VirtualPathUtility blows up if there is a // query string, so we have to account for this. int queryStringStartIndex = originalUrl.IndexOf('?'); if (queryStringStartIndex != -1) { string queryString = originalUrl.Substring(queryStringStartIndex); string baseUrl = originalUrl.Substring(0, queryStringStartIndex); return string.Concat( VirtualPathUtility.ToAbsolute(baseUrl), queryString); } else { return VirtualPathUtility.ToAbsolute(originalUrl); } } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <param name="forceHttps">if true forces the url to use https</param> /// <returns></returns> public static string ResolveServerUrl(string serverUrl, bool forceHttps) { if (string.IsNullOrEmpty(serverUrl)) return serverUrl; // *** Is it already an absolute Url? if (serverUrl.IndexOf("://") > -1) return serverUrl; string newServerUrl = ResolveUrl(serverUrl); Uri result = new Uri(HttpContext.Current.Request.Url, newServerUrl); if (!forceHttps) return result.ToString(); else return ForceUriToHttps(result).ToString(); } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// It work like Page.ResolveUrl, but adds these to the beginning. /// This method is useful for generating Urls for AJAX methods /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <returns></returns> public static string ResolveServerUrl(string serverUrl) { return ResolveServerUrl(serverUrl, false); } /// <summary> /// Forces the Uri to use https /// </summary> private static Uri ForceUriToHttps(Uri uri) { // ** Re-write Url using builder. UriBuilder builder = new UriBuilder(uri); builder.Scheme = Uri.UriSchemeHttps; builder.Port = 443; return builder.Uri; }
# re: ResolveUrl() without Page
Thanks.
# re: ResolveUrl() without Page
// *** Absolute path - just return if (originalUrl.IndexOf("://") != -1) return originalUrl;
the cause of the bug is just here. you see, there are cases when the absolute path specifier exists in the path beeing resolved but it is a part of a querystring parameter:
~/pathtoresolve/page.aspx?returnurl=http://servertoredirect/resource.aspx
in fact what you should then do is not only to check if the url contains the :// but also if it contains the query string parameter separator, "?", positioned BEFORE the ://.
my quick hack around this is:
/// <summary> /// Returns a site relative HTTP path from a partial path starting out with a ~. /// Same syntax that ASP.Net internally supports but this method can be used /// outside of the Page framework. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="originalUrl">Any Url including those starting with ~</param> /// <returns>relative url</returns> public static string ResolveUrl( string originalUrl ) { if ( string.IsNullOrEmpty( originalUrl ) ) return originalUrl; // *** Absolute path - just return int IndexOfSlashes = originalUrl.IndexOf( "://" ); int IndexOfQuestionMarks = originalUrl.IndexOf( "?" ); if ( IndexOfSlashes > -1 && ( IndexOfQuestionMarks < 0 || ( IndexOfQuestionMarks > -1 && IndexOfQuestionMarks > IndexOfSlashes ) ) ) return originalUrl; // *** We don't start with the '~' -> we don't process the Url if ( !originalUrl.StartsWith( "~" ) ) return originalUrl; // *** Fix up path for ~ root app dir directory // VirtualPathUtility blows up if there is a // query string, so we have to account for this. int queryStringStartIndex = originalUrl.IndexOf( '?' ); if ( queryStringStartIndex != -1 ) { string queryString = originalUrl.Substring( queryStringStartIndex ); string baseUrl = originalUrl.Substring( 0, queryStringStartIndex ); return string.Concat( VirtualPathUtility.ToAbsolute( baseUrl ), queryString ); } else { return VirtualPathUtility.ToAbsolute( originalUrl ); } } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <param name="forceHttps">if true forces the url to use https</param> /// <returns></returns> public static string ResolveServerUrl( string serverUrl, bool forceHttps ) { if ( string.IsNullOrEmpty( serverUrl ) ) return serverUrl; // *** Is it already an absolute Url? int IndexOfSlashes = serverUrl.IndexOf( "://" ); int IndexOfQuestionMarks = serverUrl.IndexOf( "?" ); if ( IndexOfSlashes > -1 && ( IndexOfQuestionMarks < 0 || ( IndexOfQuestionMarks > -1 && IndexOfQuestionMarks > IndexOfSlashes ) ) ) return serverUrl; string newServerUrl = ResolveUrl( serverUrl ); Uri result = new Uri( HttpContext.Current.Request.Url, newServerUrl ); if ( !forceHttps ) return result.ToString(); else return ForceUriToHttps( result ).ToString(); } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// It work like Page.ResolveUrl, but adds these to the beginning. /// This method is useful for generating Urls for AJAX methods /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <returns></returns> public static string ResolveServerUrl( string serverUrl ) { return ResolveServerUrl( serverUrl, false ); } /// <summary> /// Forces the Uri to use https /// </summary> private static Uri ForceUriToHttps( Uri uri ) { // ** Re-write Url using builder. UriBuilder builder = new UriBuilder( uri ); builder.Scheme = Uri.UriSchemeHttps; builder.Port = 443; return builder.Uri; }
# re: ResolveUrl() without Page
# re: ResolveUrl() without Page
/// <summary> /// Returns a site relative HTTP path from a partial path starting out with a ~. /// Same syntax that ASP.Net internally supports but this method can be used /// outside of the Page framework. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="originalUrl">Any Url including those starting with ~</param> /// <returns>relative url</returns> public static string ResolveUrl(string originalUrl) { if (string.IsNullOrEmpty(originalUrl)) return originalUrl; // *** Absolute path - just return if (IsAbsolutePath(originalUrl)) return originalUrl; // *** We don't start with the '~' -> we don't process the Url if (!originalUrl.StartsWith("~")) return originalUrl; // *** Fix up path for ~ root app dir directory // VirtualPathUtility blows up if there is a // query string, so we have to account for this. int queryStringStartIndex = originalUrl.IndexOf('?'); if (queryStringStartIndex != -1) { string queryString = originalUrl.Substring(queryStringStartIndex); string baseUrl = originalUrl.Substring(0, queryStringStartIndex); return string.Concat( VirtualPathUtility.ToAbsolute(baseUrl), queryString); } else { return VirtualPathUtility.ToAbsolute(originalUrl); } } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// Works like Control.ResolveUrl including support for ~ syntax /// but returns an absolute URL. /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <param name="forceHttps">if true forces the url to use https</param> /// <returns></returns> public static string ResolveServerUrl(string serverUrl, bool forceHttps) { if (string.IsNullOrEmpty(serverUrl)) return serverUrl; // *** Is it already an absolute Url? if(IsAbsolutePath(serverUrl)) return serverUrl; string newServerUrl = ResolveUrl(serverUrl); Uri result = new Uri(HttpContext.Current.Request.Url, newServerUrl); if (!forceHttps) return result.ToString(); else return ForceUriToHttps(result).ToString(); } /// <summary> /// This method returns a fully qualified absolute server Url which includes /// the protocol, server, port in addition to the server relative Url. /// /// It work like Page.ResolveUrl, but adds these to the beginning. /// This method is useful for generating Urls for AJAX methods /// </summary> /// <param name="ServerUrl">Any Url, either App relative or fully qualified</param> /// <returns></returns> public static string ResolveServerUrl(string serverUrl) { return ResolveServerUrl(serverUrl, false); } /// <summary> /// Forces the Uri to use https /// </summary> private static Uri ForceUriToHttps(Uri uri) { // ** Re-write Url using builder. UriBuilder builder = new UriBuilder(uri); builder.Scheme = Uri.UriSchemeHttps; builder.Port = 443; return builder.Uri; } private static bool IsAbsolutePath(string originalUrl) { // *** Absolute path - just return int IndexOfSlashes = originalUrl.IndexOf("://"); int IndexOfQuestionMarks = originalUrl.IndexOf("?"); if (IndexOfSlashes > -1 && (IndexOfQuestionMarks < 0 || (IndexOfQuestionMarks > -1 && IndexOfQuestionMarks > IndexOfSlashes) ) ) return true; return false; }
# re: ResolveUrl() without Page
# re: ResolveUrl() without Page
Page p = HttpContext.Current.Handler as Page;That should be all. Maybe its better, if you add a check for null, but it's for me to easiest solution.
But thanks for your snippet ;)
# re: ResolveUrl() without Page
# re: ResolveUrl() without Page
Maybe this is naive, but why not just pass in...
this.Page
...when needed?
That is really just a point to the Page object, is it not, so the overhead is minimal?
I suppose we can say "do not break the purity of the BusinessLayer responsibility by passing a PresentationLayer object into it", which is a purist view that I can see-- but, aside from that, why not pass down "this.Page" as necessary?
Please advise.
Thank you.
-- Mark Kamoski
# re: ResolveUrl() without Page
BTW, this page gave me the following RTE in IE8....
Line: 1206
Error: 'get(...)' is null or not an object
...so I thought you should know.
HTH.
Thank you.
-- Mark Kamoski
# re: ResolveUrl() without Page
Rick Strahl's Web Log has been very helpful in the past so I thought I'd post my solution here. There's probably a thousand better ways to do it but posting something that may be helpful is better than nothing at all!
public class MyClass { public static string URLRoot { get { string CurrentURL = HttpContext.Current.Request.Url.ToString(); if (CurrentURL.IndexOf("?") == -1) { CurrentURL = CurrentURL + "?"; } string CurrentFile = HttpContext.Current.Request.CurrentExecutionFilePath.ToString(); if (CurrentFile.IndexOf("?") == -1) { CurrentFile = CurrentFile + "?"; } string CurrentQueryString = HttpContext.Current.Request.QueryString.ToString(); if (!MyClass.ValueIsEmpty(CurrentQueryString)) { CurrentURL = CurrentURL.Replace(CurrentQueryString, ""); } if (!MyClass.ValueIsEmpty(CurrentFile)) { CurrentURL = CurrentURL.Replace(CurrentFile, ""); } string VirtualDirectory = HttpContext.Current.Request.ApplicationPath.ToString(); CurrentURL = CurrentURL + VirtualDirectory + "/"; CurrentURL = CurrentURL.Replace("//", "/"); CurrentURL = CurrentURL.Replace("http:/", "http://"); CurrentURL = CurrentURL.Replace("https:/", "https://"); return CurrentURL; } } public static bool ValueIsEmpty(string StringValue) { if (StringValue == String.Empty || StringValue == null || StringValue.Length < 1 || StringValue == "") { return true; } else { return false; } } }
To use this, just put something like the following in your code behind:
Image1.ImageUrl = MyClass.URLRoot + "img/myimage.png";
# re: ResolveUrl() without Page
this blog was very helpful for me.
I had the problem that sessionid (cookieless=true) changed if i use resolveurl in my class.
But someone postet following code in one of the comments
Dim p As Page = HttpContext.Current.Handler
and this was very very helpful for me.
Many thanks
Luzie (Frankfurt, Germany)
# re: ResolveUrl() without Page
This is very helpfull code, can you tell me how to do the same with the URL in Iframe,
i mean resolveURL w.r.t Iframe URL would be very helpfull,
i tried iFrame.ResolveUrl(relativeUrl), but no luck...
Thanks,
Kumar
# Problem with your code formatting
It makes the code really annoying to copy-paste.
See: http://stackoverflow.com/questions/4838005/vs2010-adds-additional-white-lines-between-pasted-code
Apart from that: Great blog, I love it. :)
# re: ResolveUrl() without Page
I want to include both LaTeX code snippet and C# code snippet in my little book about LaTeX. However, I could not find the way to fix margin overflow for LTXexample.
Please see my screenshot below, you will get the idea:
alt text
And the "minimal code" is given as follows:<a href="http: peelingacne.com // ">peelingacne</a> because there is no "showexpl" tag, so I choose "listings and margins" tags.
EDIT 1: There is no margin overflow for lstlisting. I can control lstlisting margins using lstset as given in the code snippet above.
# re: ResolveUrl() without Page
/// <summary>
/// Resolve client URLs without a page context
/// </summary>
/// <param name="vobjContext">The </param>
/// <param name="vstrOriginalUrl"></param>
/// <returns></returns>
public static string ResolveUrl(this HttpContext vobjContext, string vstrOriginalUrl)
{
// empty url
if (string.IsNullOrEmpty(vstrOriginalUrl))
{
return vstrOriginalUrl;
}
// absolute path
if (vstrOriginalUrl.Contains("://"))
{
return vstrOriginalUrl;
}
// fix ~ Urls
if (vstrOriginalUrl.StartsWith("~"))
{
if (vobjContext != null && vobjContext.Request != null)
{
return vobjContext.Request.ApplicationPath + vstrOriginalUrl.Substring(1).Replace("//", "/");
}
else
{
throw new ArgumentException("URL Resolve failed - possible bad HttpContext.");
}
}
// catch all
return vstrOriginalUrl;
}
# re: ResolveUrl() without Page