Based on my personal experience using ASP.NET, and through searching on the Internet. I found that Page's ResolveUrl method brought us some serious problems.
The most common problem is that it cannot be used outside the scope of the page or control.
All other problems are bugs. For example, it cannot correctly handle some URLs you give. For example, try Page.ResolveUrl("~/test.aspx?param=http://www.test.com"). The result is the same as the string you entered, without any changes. Using Reflector to view the asp.net code, I found that the mechanism for converting relative URLs to absolute URLs first searches for "://" in the string, and if found, returns it directly. Therefore, if you pass a parameter with ://, the query string is OK. We all know that query string parameters should be urlencoded, but if not, it should still be acceptable for the URL. Seriously, check your browser.
Online, the recommended approach is to use VirtualPathUtility.ToAbsolute, which is quite nice and convenient if you are passing the URL as query string,...otherwise, an exception will be thrown. If it is an absolute URL, it will also throw an exception!
So, I decided to look for a final solution.
First, I'm looking for a good variable that will give us the virtual path while the application is running, without using the page context.
I used HttpRuntime.AppDomainAppVirtualPath. It can be used anywhere - even in timer callbacks! It doesn't have a trailing slash in the path, ASP.NET has idiosyncratically eliminated the slashes, but we can fix it :-)
Then, I did some testing using the original ResolveUrl code and found out how to replace it with AppVirtualPath:
1. When the URL starts with a slash (/ or ), it will not be changed!
2. When the URL starts with 〜/, it will be replaced by AppVirtualPath.
3. When the URL is an absolute URL, it will not be changed.
4. In any other case (even starting with 〜 instead of a slash), the URL will be appended to the AppVirtualPath.
5. Whenever it modifies the URL, it also fixes slashes. Remove the double slash and replace with /.
Code:
code
public static string ResolveUrl(string relativeUrl)
{
if (relativeUrl == null) throw new ArgumentNullException("relativeUrl");
if (relativeUrl.Length == 0 || relativeUrl[0] == '/' ||
relativeUrl[0] == '\') return relativeUrl;
int idxOfScheme =
relativeUrl.IndexOf(@"://", StringComparison.Ordinal);
if (idxOfScheme != -1)
{
int idxOfQM = relativeUrl.IndexOf('?');
if (idxOfQM == -1 || idxOfQM > idxOfScheme) return relativeUrl;
}
StringBuilder sbUrl = new StringBuilder();
sbUrl.Append(HttpRuntime.AppDomainAppVirtualPath);
if (sbUrl.Length == 0 || sbUrl[sbUrl.Length - 1] != '/') sbUrl.Append('/');
// found question mark already? query string, do not touch!
bool foundQM = false;
bool foundSlash; // the latest char was a slash?
if (relativeUrl.Length > 1
&& relativeUrl[0] == '~'
&& (relativeUrl[1] == '/' || relativeUrl[1] == '\'))
{
relativeUrl = relativeUrl.Substring(2);
foundSlash = true;
}
else foundSlash = false;
foreach (char c in relativeUrl)
{
if (!foundQM)
{
if (c == '?') foundQM = true;
else
{
if (c == '/' || c == '\')
{
if (foundSlash) continue;
else
{
sbUrl.Append('/');
foundSlash = true;
continue;
}
}
else if (foundSlash) foundSlash = false;
}
}
sbUrl.Append(c);
}
return sbUrl.ToString();
}
After completing the code and comparing the original ResolveUrl test over and over again, I started testing performance... In most cases, my code executed 2.7 times faster than the original ResolveUrl! I also tested it inside a loop, executing the code 100000 times with different URLs.
Reference original text: http://www.codeproject.com/KB/aspnet/resolveurl.aspx
Author: Zhu Qilin Source: http://zhuqil.cnblogs.com
The copyright of this article belongs to the author and Blog Park. Reprinting is welcome. However, this statement must be retained without the author's consent, and a link to the original text must be provided in an obvious position on the article page. Otherwise, the right to pursue legal liability is reserved.