在应用URLRewrite功能后自动输出重写过的URL

来源:互联网 发布:知乎痴情叔被骂 编辑:程序博客网 时间:2024/06/05 07:29

前两天看了老赵的重提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 configsUrlsCollection 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 &amp; which is used in XML files    sendTo = sendTo.Replace("?", "\\?").Replace("&amp;", "&");    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 HTMLbyte[] outdata = Encoding.UTF8.GetBytes(string.Join("href=", body));//Render to browserm_sink.Write(outdata, 0, outdata.GetLength(0));

四、小结

至此,我们这个简单的URL自动重写功能就实现了,当然,其中还有很多需要完善和考虑到地方,比如如何处理Javascript中的location.href等等。由于本例纯属“自动重写URL”这种方法的可行性研究,所以使用的都是假设的场景,并没有在实践项目中应用,在此仅作块砖头,有玉的尽管来砸吧。

PS:由于下午要回家过年,所以写的比较匆忙,还请大家见谅。本人第一次发首页帖,因为没有看到过类似的文章,所以就发在了首页上,其实没什么技术性,如有觉得不妥,我立马撤下:)。

原创粉丝点击