在应用URLRewrite功能后自动输出重写过的URL
前两天看了老赵的重提URL Rewrite(4):不同级别URL Rewrite的一些细节与特点,并且有人留言问怎样自动输出重写后的URL。我看到之后非常有想法,事实上在我以前研究URL重写的时候也想过这个问题,如果有这种方法的话,将会给我们开发带来大大的方便。正好不久前我刚整理了一下HTML页面生成的方法,里面的Response.Filter给了我很大的灵感。好的,说干就干,花了昨天半天时间,捣鼓出来一个简单的例子,所以也就有了本文。
一、思考
我们在项目中使用URL重写技术,来达到对搜索引擎的友好、人性化URL、清晰的组织架构、新老系统整合等等效果,但同时也给我们的开发带来了一些不便之处。比如VS就会提醒您这个URL并不存在,也给我们的调试工作加大了难度。如果是老系统升级使用URL重写功能的话,那整个URL替换一下也是个不小的工程。如果我们能在HTML产生之后输出之前做些小动作的话,也许能够满足我们的需求。
二、准备
- 生成好的HTML。这点简单,使用Response.Filter就可以了。如果对Response.Filter还不了解到话,请看这,本文就不多说了。
- 替换。这点也不难,但需要考虑的是怎么样达到最优化,还请大家来讨论,下面就来说说我的实现。
三、实现
- URL替换规则
要使用URL重写,那我们在Config里肯定对重写规则有所定义。简单的方法就是定义四条,两条对应URL重写,两条对应URL替换,但好像比较烦哦,正是我们程序员不屑做的事。而且我们这里的URL替换规则正好是前面的这个重写规则的反向,那就用程序来实现吧。我的实现代码:
//Get URL rewrite configs UrlsCollection rules = UrlsConfig.GetConfig().Urls; string[] virtualUrl = new string[rules.Count]; string[] destinationUrl = new string[rules.Count]; for (int j = 0; j < rules.Count; j++) { //Remove ~/ string lookFor = rules[j].VirtualUrl.Substring(2); string sendTo = rules[j].DestinationUrl.Substring(2); //Replace ? with \\? for Regex //Replace & which is used in XML files sendTo = sendTo.Replace("?", "\\?").Replace("&", "&"); string[] array_lookFor = lookFor.Split(new string[] { "(.*)" }, StringSplitOptions.None); string[] array_sendTo = sendTo.Split('$'); //Prepare new lookFor and sendTo for (int i = 0; i < array_lookFor.Length - 1; i++) { string initial; if (array_sendTo[i + 1].Length == 1) { initial = array_sendTo[i + 1]; array_sendTo[i + 1] = ""; } else { initial = array_sendTo[i + 1].Remove(1); array_sendTo[i + 1] = array_sendTo[i + 1].Substring(1, array_sendTo[i + 1].Length - 1); } array_lookFor[i + 1] = initial + array_lookFor[i + 1]; } //Join with new Regex characters virtualUrl[j] = "^" + string.Join("(.*)", array_sendTo) + "$"; destinationUrl[j] = string.Join("$", array_lookFor); }
我做了张图,时间紧,比较丑,但足以说明事情了。
做了如上图的替换之后,在用新的分隔符链接起来,就变成了我们所需要的正则表达式了。
- 开始替换
有了正则表达式,替换就简单了。我的实现代码:
string[] body = Encoding.UTF8.GetString(data).Split(new string[] { "href=" }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < body.Length; i++) { string s = body[i]; for (int j = 0; j < virtualUrl.Length; j++) { Regex re = new Regex(virtualUrl[j], RegexOptions.IgnoreCase); //<a href="....."> if (s.StartsWith("\"")) { string href = s.Substring(1, s.Substring(1).IndexOf('"')); if (re.IsMatch(href)) { string newhref = re.Replace(href, destinationUrl[j]); body[i] = "\"" + path + newhref + s.Substring(s.Substring(1).IndexOf('"') + 1); } } //<a href='.....'> else if (s.StartsWith("'")) { string href = s.Substring(1, s.Substring(1).IndexOf('\'')); if (re.IsMatch(href)) { string newhref = re.Replace(href, destinationUrl[j]); body[i] = "'" + path + newhref + s.Substring(s.Substring(1).IndexOf('\'') + 1); } } //<a href=.....> else { //The operation is not implemented. } } }
首先用"href="来分割一下,然后再来判断URL是由 "" 或 '' 或“什么都没有”来包住URL的,其中第三个比较麻烦,我也就没有具体来实现它。同时我也没有做Trim、去掉换行等操作。
- 输出
替换完了HTML,我们再用"href="组合起来,就可以输出了。
//Get formative HTML byte[] outdata = Encoding.UTF8.GetBytes(string.Join("href=", body)); //Render to browser m_sink.Write(outdata, 0, outdata.GetLength(0));
四、小结
至此,我们这个简单的URL自动重写功能就实现了,当然,其中还有很多需要完善和考虑到地方,比如如何处理Javascript中的location.href等等。由于本例纯属“自动重写URL”这种方法的可行性研究,所以使用的都是假设的场景,并没有在实践项目中应用,在此仅作块砖头,有玉的尽管来砸吧。
PS:由于下午要回家过年,所以写的比较匆忙,还请大家见谅。本人第一次发首页帖,因为没有看到过类似的文章,所以就发在了首页上,其实没什么技术性,如有觉得不妥,我立马撤下:)。
posted on 2008-02-05 11:02 Superstone 阅读(2385) 评论(5) 编辑 收藏 举报