类别 ID 类别名称

1

饮料

2

调味品

3

糖果

4

奶制品

...

...

假设我们已创建了名为 ListProductsByCategory.aspx 的 ASP.NET 网页,该网页在查询字符串中接受类别 ID 值,并显示属于该类的所有产品。因此,要查看我们销售的饮料的用户可以访问 ListProductsByCategory.aspx?CategoryID=1,而那些要查看奶制品的用户可以访问 ListProductsByCategory.aspx?CategoryID=4。此外,还假设我们有一个名为 ListCategories.aspx 的页面,该页面列出了待售的所有产品类别。

很显然,这是一个 URL 重写事例,因为提供给用户的 URL 没有为用户带来任何意义,也没有为他们提供任何“可删节性”。因此,让我们使用 URL 重写,以便在用户访问 /Products/Beverages.aspx 时,他们的 URL 将被重写为 ListProductsByCategory.aspx?CategoryID=1。我们可以在 Web.config 文件中使用以下 URL 重写规则来实现此功能。

<RewriterConfig>
   <Rules>
      <!-- 产品制表者规则 -->
      <RewriterRule>
         <LookFor>~/Products/Beverages\.aspx</LookFor>
         <SendTo>~/ListProductsByCategory.aspx?CategoryID=1</SendTo>
      </RewriterRule>
      <RewriterRule>
   </Rules>
</RewriterConfig>

正如您可以看到的,此规则将进行搜索,以查看用户请求的路径是否为 /Products/Beverages.aspx。如果是,它便将 URL 重写为 /ListProductsByCategory.aspx?CategoryID=1。

注意:请注意,<LookFor> 元素对 Beverages.aspx 中的句点进行了转义。这是因为在正则表达式模式中使用了 <LookFor> 值,并且句点是正则表达式中的特殊字符,该字符表示“匹配任意字符”,例如,与 URL /Products/BeveragesQaspx 匹配。通过转义句点(使用 \.),可以表明我们要匹配的是文字句点,而不是任何旧的字符。

有了此规则之后,当用户访问 /Products/Beverages.aspx 时,页面上将显示待售的饮料。图 3 显示了访问 /Products/Beverages.aspx 的浏览器的快照。请注意,在浏览器的地址栏中,URL 将读取 /Products/Beverages.aspx,但用户实际看到的是 ListProductsByCategory.aspx?CategoryID=1 的内容。(实际上,Web 服务器上根本不存在 /Products/Beverages.aspx 文件!)


图 3. 重写 URL 之后请求类别

与 /Products/Beverages.aspx 相似,下面我们要为其他产品类别添加重写规则。此操作仅包括在 Web.config 文件的 <Rules> 元素内添加附加的 <RewriterRule> 元素。请参阅下载内容中的 Web.config 文件,以获取用于此演示的一组完整的重写规则。

为了使 URL 更具可删节性,最好使用户只需从 /Products/Beverages.aspx 中删除 Beverages.aspx 即可看到产品类别的列表。乍一看,这可能是一项很普通的任务(只需添加一个将 /Products/ 映射到 /ListCategories.aspx 的重写规则即可)。但此操作存在一个微妙之处,即您必须首先创建一个 /Products/ 目录,并在 /Products/ 目录中添加一个空的 Default.aspx 文件。

要理解需要执行这些额外步骤的原因,可以参考前面的内容,即 URL 重写引擎位于 ASP.NET 级别上。也就是说,如果 ASP.NET 引擎永远没有机会处理请求,URL 重写引擎就没有办法检测传入的 URL。而且,请记住,仅当被请求的文件具有相应的扩展名时,IIS 才会将传入请求传递给 ASP.NET 引擎。因此,如果用户访问 /Products/,而 IIS 没有看到任何文件扩展名,那么它将检查目录,以查看是否存在这样一个文件,即该文件名为默认文件名中的一个。(Default.aspx、Default.htm、Default.asp 等等。“IIS 管理”对话框中“Web 服务器属性”对话框的“文档”选项卡对这些默认文件名进行了定义。)当然,如果 /Products/ 目录不存在,IIS 将返回 HTTP 404 错误。

因此,我们需要创建 /Products/ 目录。另外,我们还需要在此目录中创建一个文件 Default.aspx。这样,当用户访问 /Products/ 时,IIS 将检测目录,查看是否存在一个名为 Default.aspx 的文件,然后将处理过程传递给 ASP.NET 引擎。然后,URL 重写器将在重写 URL 时分解。

创建目录和 Default.aspx 文件后,请继续操作,并向 <Rules> 元素中添加以下重写规则:

<RewriterRule>
   <LookFor>~/Products/Default\.aspx</LookFor>
   <SendTo>~/ListCategories.aspx</SendTo>
</RewriterRule>

有了此规则之后,当用户访问 /Products/ 或 /Products/Default.aspx 时,他们将看到产品类别列表,如图 4 所示。


4. 向 URL 添加“可删节性”

处理回发

如果要重写的 URL 中包含一个服务器端的 Web 窗体并执行回发,则窗体回发后,将使用带下划线的 URL。也就是说,如果用户在浏览器中输入 /Products/Beverages.aspx,他们在浏览器地址栏中看到的将是 /Products/Beverages.aspx,但是他们看到的内容将是 ListProductsByCategory.aspx?CategoryID=1 的内容。如果 ListProductsByCategory.aspx 执行了回发,用户将被回发到 ListProductsByCategory.aspx?CategoryID=1,而不是 /Products/Beverages.aspx。这样不会中断任何内容,但从用户的角度考虑,如果单击按钮时突然看到 URL 更改会使他们感到不安。

出现这种情况的原因是:在呈现 Web 窗体时,它会将其操作属性直接设置为 Request 对象中文件路径的值。当然,在呈现 Web 窗体时,URL 已从 /Products/Beverages.aspx 重写为 ListProductsByCategory.aspx?CategoryID=1,这表明 Request 对象报告用户要访问 ListProductsByCategory.aspx?CategoryID=1。只需使服务器端窗体不呈现操作属性即可解决此问题。(默认情况下,如果窗体不包含操作属性,浏览器将会回发。)

不幸的是,Web 窗体不允许您明确指定操作属性,也不允许您设置某些属性以禁用操作属性的呈现。因此,我们必须自己来扩展 System.Web.HtmlControls.HtmlForm 类,覆盖 RenderAttribute() 方法并明确指出它不会呈现操作属性。

由于继承功能,我们可以获得 HtmlForm 类的所有功能,并且只需添加几行代码即可获得所需的行为。以下显示了自定义类的完整代码:

namespace ActionlessForm {
  public class Form : System.Web.UI.HtmlControls.HtmlForm
  {
     protected override void RenderAttributes(HtmlTextWriter writer)
     {
        writer.WriteAttribute("name", this.Name);
        base.Attributes.Remove("name");

        writer.WriteAttribute("method", this.Method);
        base.Attributes.Remove("method");

        this.Attributes.Render(writer);

        base.Attributes.Remove("action");

        if (base.ID != null)
           writer.WriteAttribute("id", base.ClientID);
     }
  }
}

已被覆盖的 RenderAttributes() 方法的代码仅包含 HtmlForm 类的 RenderAttributes() 方法的准确代码,而不设置操作属性。(我使用 Lutz Roeder 的 Reflector 来查看 HtmlForm 类的源代码。)

创建此类并对其进行编译之后,要在 ASP.NET Web 应用程序中使用它,应首先将其添加到 Web 应用程序的 References 文件夹中。然后,要使用它来代替 HtmlForm 类,只需在 ASP.NET 网页的顶部添加以下内容即可:

<%@ Register TagPrefix="skm" Namespace="ActionlessForm" 
   Assembly="ActionlessForm" %>

然后,将 <form runat="server">(如果有)替换为:

<skm:Form id="Form1" method="post" runat="server">

并将右边的 </form> 标记替换为:

</skm:Form>

您可以在 ListProductsByCategory.aspx(包含在本文的下载代码中)中发现操作中的此自定义 Web Form 类。下载内容中还包含了用于无操作 Web Form 的 Visual Studio .NET 项目。

注意:如果要重写的目标 URL 没有执行回发,则无需使用此自定义 Web Form 类。

返回页首

创建真正“可删节”的 URL

前一部分中介绍的简单 URL 重写显示了如何轻松地为 URL 重写引擎配置新的重写规则。但在使用正则表达式时,重写规则的真正功能才会发挥更大作用,本部分将对此进行探讨。

Blog 在当今正变得越来越流行,似乎每个人都拥有自己的 blog。如果您不熟悉 blog:blog 是经常更新的个人页面,通常作为联机期刊。大多数 blog 只记录每天发生的事情,还有一些 blog 可能关注于特定的主题(例如,电影回顾、体育团队或计算机技术)。

可以在任何地点对 blog 进行更新,更新频率为从每天几次到每周一次或两次,具体情况取决于作者。通常,blog 主页将显示最近的 10 个条目,但实际上,所有 blog 软件均提供存档,访问者可以通过存档读取较早的帖子。Blog 是用于“可删节”URL 的一个功能强大的应用程序。假设在搜索 blog 的存档时,您在 URL /2004/02/14.aspx 上发现了您自己。如果您发现自己在阅读 2004 年 2 月 14 日的帖子,您是否觉得很惊讶?而且,您可能希望查看 2004 年 2 月的所有帖子,在这种情况下,您可以尝试将 URL 删节为 /2004/02/。要查看 2004 年的所有帖子,您可以尝试访问 /2004/。

维护 blog 时,最好为访问者提供此级别的 URL“可删节性”。许多 blog 引擎都提供此功能,但我们将讨论如何使用 URL 重写来实现此功能。

首先,我们需要一个 ASP.NET 网页,此页面将按照日、月或年来显示 blog 条目。假设我们有一个 ShowBlogContent.aspx 页面,该页面的查询字符串参数为年、月和日。要查看 2004 年 2 月 14 日的帖子,我们可以访问 ShowBlogContent.aspx?year=2004&month=2&day=14。要查看 2004 年 2 月的所有帖子,我们可以访问 ShowBlogContent.aspx?year=2004&month=2。最后,要查看 2004 年的所有帖子,我们可以浏览到 ShowBlogContent.aspx?year=2004。(可以在本文的下载内容中找到 ShowBlogContent.aspx 的代码。)

在这种情况下,如果用户访问 /2004/02/14.aspx,我们需要将 URL 重写为 ShowBlogContent.aspx?year=2004&month=2&day=14。所有三种情况(URL 指定了年、月和日时;URL 仅指定了年和月时;URL 仅指定了年时)均可使用重写规则进行处理:

<RewriterConfig>
   <Rules>
      <!-- Blog 内容显示程序规则 -->
      <RewriterRule>
         <LookFor>~/(\d{4})/(\d{2})/(\d{2})\.aspx</LookFor>
         <SendTo>~/ShowBlogContent.aspx?year=$1&amp;month=$2&amp;day=$3</SendTo>
      </RewriterRule>
      <RewriterRule>
         <LookFor>~/(\d{4})/(\d{2})/Default\.aspx</LookFor>
         <SendTo><![CDATA[~/ShowBlogContent.aspx?year=$1&month=$2]]></SendTo>
      </RewriterRule>
      <RewriterRule>
         <LookFor>~/(\d{4})/Default\.aspx</LookFor>
         <SendTo>~/ShowBlogContent.aspx?year=$1</SendTo>
      </RewriterRule>
   </Rules>
</RewriterConfig>

这些重写规则表明了正则表达式的功能。在第一个规则中,我们使用模式 (\d{4})/(\d{2})/(\d{2})\.aspx 查找 URL。在简明英语中,它对应了这样一个字符串:首先是四个数字,后跟一个斜杠,然后是两个数字,后跟一个斜杠,然后再跟两个数字,最后是一个 .aspx。每个数字组周围的括号非常重要,通过它可以在相应的 <SendTo> 属性中引用这些括号内的匹配字符。 特别是,我们可以针对第一、第二和第三个括号组分别使用 $1、$2 和 $3 引用回括号内的

上一页  [1] [2] [3] [4]  下一页

打印本文 打印本文 关闭窗口 关闭窗口
在 ASP.NET 中执行 URL 重写
作者:武汉SEO闵涛  文章来源:敏韬网  点击数3539  更新时间:2009/4/23 10:45:28  文章录入:mintao  责任编辑:mintao
类,并负责执行实际的 URL 重写。ModuleRewriter 包含单一覆盖方法(Rewrite()),如下所示:

protected override void Rewrite(string requestedPath, 
   System.Web.HttpApplication app)
{
   // 获得配置规则
   RewriterRuleCollection rules = 
     RewriterConfiguration.GetConfig().Rules;

   // 遍历每个规则...
   for(int i = 0; i < rules.Count; i++)
   {
      // 获得要查找的模式,并且
      // 解析 Url(转换为相应的目录)
      string lookFor = "^" + 
        RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, 
        rules[i].LookFor) + "$";

      // 创建 regex(请注意,已设置 IgnoreCase...)
      Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);

      // 查看是否找到了匹配的规则
      if (re.IsMatch(requestedPath))
      {
         // 找到了匹配的规则 -- 进行必要的替换
         string sendToUrl = 
RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, 
            re.Replace(requestedPath, rules[i].SendTo));

         // 重写 URL
         RewriterUtils.RewriteUrl(app.Context, sendToUrl);
         break;      // 退出 For 循环
      }
   }
}

Rewrite() 方法从获取 Web.config 文件中的一组重写规则开始。然后,它将遍历重写规则,每次遍历一个,对于每个规则,它将获取规则的 LookFor 属性,并使用正则表达式来确定是否在被请求的 URL 中找到了匹配的规则。

如果找到了匹配的规则,将在具有 SendTo 属性值的被请求路径上执行正则表达式替换。然后,替换后的 URL 将被传递到 RewriterUtils.RewriteUrl() 方法中。RewriterUtils 是一个 helper 类,此类将提供一对由 URL 重写 HTTP 模块和 HTTP 处理程序使用的静态方法。RewriterUrl() 方法仅调用 HttpContext 对象的 RewriteUrl() 方法。

注意:您可能已注意到,执行正则表达式匹配和替换时,将调用 RewriterUtils.ResolveUrl()。此 helper 方法只替换具有应用程序路径值的字符串中的所有 ~ 实例。

URL 重写引擎的整个代码可随本文下载。我们已经介绍了大部分密切相关的组件,但还有一些其他组件(例如,对 Web.config 文件中 XML 格式的重写规则进行反序列化以使其成为对象的类),以及用于 URL 重写的 HTTP 处理程序工厂。本文剩余的三个部分将对 URL 重写的实际使用情况进行介绍。

返回页首

使用 URL 重写引擎执行简单的 URL 重写

为了实际演示 URL 重写引擎,我们来构建一个使用简单 URL 重写的 ASP.NET Web 应用程序。假设我们所工作的公司通过网络销售分类产品。这些产品分为以下几个类别:

打印本文 打印本文 关闭窗口 关闭窗口