ResolveUrl in ASP.NET - The Perfect Solution
Introduction/Background
From my personal experience using ASP.NET, and from searching the web, I have found that the ResolveUrlmethod of the Page control (and basically, Control) presents us with some serious problems.
The most common one is that you just cannot use it outside of the page or control context.
Other problems are just bugs. It will not correctly handle some of the URLs you'll give it. For example, tryPage.ResolveUrl("~/test.aspx?param=http://www.test.com"). The result is the very same input string... It will just do nothing. By looking into the ASP.NET code using Reflector, I found that all mechanisms that are supposed to convert the relative URLs to absolute URLs will search first for a "://" inside the string, and will return if found. So a query string is OK, unless you pass in a parameter with ://. Yes, I know that the query string parameter should be UrlEncoded, but if it isn't, it is still an acceptable URL. Seriously, check your browsers!
Other suggested methods on the web involve using VirtualPathUtility.ToAbsolute, which is pretty nice and handy, unless you pass in a query string with the URL... Because it will just throw an exception. It will also throw an exception for an absolute URL!
So I decided to find the ultimate solution.
Using the Code
First, I searched for the perfect variable that will give me the Application Virtual Path at runtime without a page context.
I found this to be HttpRuntime.AppDomainAppVirtualPath. It will work anywhere - even inside a timer callback! It gives the path without a trailing slash (ASP.NET makes a special effort to remove the trailing slash...), but that is OK, we can fix it 
Then, I did some tests on the original ResolveUrl code, and found where I need to replace what with theAppVirtualPath:
- When the URL begins with a slash (either / or \), it will not touch it!
- When the URL begins with ~/, it will replace it with the
AppVirtualPath. - When the URL is an absolute URL, it will not touch it. (
ResolveUrlhas a bug with this, as I said before...) - In any other case (even beginning with ~, but not slash), it will append the URL to the
AppVirtualPath. - Whenever it modifies the URL, it also fixes up the slashes. Removes double slashes and replaces \ with /.
So I replicated all of that, but without the bugs. And here's the code:
Collapse | Copy Codepublic 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();
}
Points of Interest
After completing the code and testing over and over again and comparing to the original ResolveUrl, I started to test for performance... In most cases, my code executed faster than the original ResolveUrl by 2.7 times! I also tested inside loops that executed the code 100000s of times on different kinds of URLs.
ResolveUrl in ASP.NET - The Perfect Solution的更多相关文章
- ASP.NET Core Logging Solution
Serilog.Extensions.Logging.File This package makes it a one-liner - loggerFactory.AddFile() - to con ...
- [转]Bootstrap 3.0.0 with ASP.NET Web Forms – Step by Step – Without NuGet Package
本文转自:http://www.mytecbits.com/microsoft/dot-net/bootstrap-3-0-0-with-asp-net-web-forms In my earlier ...
- .NET & C# & ASP.NET
.NET && C# && ASP.NET https://docs.microsoft.com/zh-cn/dotnet/ .NET Documentation We ...
- error_Could not load file or assembly
原文链接 Could you be missing the loaded assembly from your configuration file? Ensure you have somethin ...
- Android 自定义 ListView 显示网络上 JSON 格式歌曲列表
本文内容 环境 项目结构 演示自定义 ListView 显示网络上 JSON 歌曲列表 参考资料 本文最开始看的是一个国人翻译的文章,没有源代码可下载,根据文中提供的代码片段,自己新建的项目(比较可恶 ...
- Thinking in Java——笔记(19)
Enumerated Types Basic enum features When you create an enum, an associated class is produced for yo ...
- Cool!15个超炫的 CSS3 文本特效【上篇】
每一个网页设计师都希望创建出让用户能够赏识的网站.当然,这是不可能满足每个人的口味的.幸运的是,我们有最强大的工具和资源.实际上,我们非常多的网站模板,框架,内容管理系统,先进的工具和其他的资源可以使 ...
- Day14 summary
Since I am writing blog in Ubuntu which has not installed Chinese language package, this blog will b ...
- NodeJS 各websocket框架性能分析
For a current project at WhoScored, I needed to learn JavaScript, Node.js and WebSocket channel, aft ...
随机推荐
- Android Fragment 真正彻底的解决(下一个)
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/37992017 上篇博客中已经介绍了Fragment产生原因.以及一些主要的使用方 ...
- node.js的npm安装
我不打算引进node.js的npm安装,但发现node.js通过管理一些包npm实现,或给一个简短的npm. 1.npm什么 npm是一个node包管理和分发工具,已经成为了非官方的公布 ...
- Java设计模式偷跑系列(十二)组合模式建模和实现
转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39828653 组合模式(Composite):组合模式有时又叫部分-总体模式.将对象组合成 ...
- SQL Server调优系列基础篇(常用运算符总结)
原文:SQL Server调优系列基础篇(常用运算符总结) 前言 上一篇我们介绍了如何查看查询计划,本篇将介绍在我们查看的查询计划时的分析技巧,以及几种我们常用的运算符优化技巧,同样侧重基础知识的掌握 ...
- UITableView的常用方法
一.UITableView的代理方法 #pragma mark 每一行的高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtI ...
- C#中如何获取系统环境变量
原文:C#中如何获取系统环境变量 C#中获取系统环境变量需要用到Environment Class.其中提供了有关当前环境和平台的信息以及操作它们的方法.该类不能被继承. 以下代码得到%systemd ...
- linux 多个源文件在编译时会产生一个目标文件
obj-m := target.o target-objs := src1.o src2.o src3.o 版权声明:本文博客原创文章.博客,未经同意,不得转载.
- WEB安全实战(五)XSS 攻击的第二种解决方式(推荐)
序 说到 XSS 攻击,前边已经有两篇文章在讲这个事了,这次又拿出来说,主要是针对近期工作中的一些新的问题.那么之前是怎么解决问题的呢?为什么又要换解决方式?以下就具体的跟大家分享一下. 旧方案 公司 ...
- 增加VMWare开机画面时间,来防止快速跳过而无法进入BIOS
用记事本打开xx.vmx,在里面添加一行: bios.bootDelay = "30000" 意思是开机后,在开机画面里停留30秒.
- 部分PC端安卓管理器使用强行断开重连的方法来连接手机,容易丢书数据,损坏数据
最近发现部分PC端的安卓管理器,貌似是百度影音以及PPTV的安卓客户端,使用强行断开手机连接,然后重新连接手机的方法,来实现客户端程序连接手机. 此时,如果刚好正在复制文件,则复制的文件会损坏,并且基 ...