IIS URL 重写和 ASP.NET 路由

作者:Ruslan Yakushev

随着 IIS 的 URL 重写模块发布以及将 ASP.NET 路由包含在 .NET Framework 4 中,ASP.NET 开发人员对这两项功能彼此的关系以及何时应使用这两个功能存在许多问题。 本文档介绍这两种技术之间的差异,并为 Web 开发人员提供有关何时使用 IIS URL 重写以及何时使用 ASP.NET 路由的指导。

从高级角度来看,这些技术似乎提供了非常相似的功能,两者都允许 Web 应用程序具有用户友好和搜索引擎友好的 URL。 但是,这两种技术之间存在根本差异,理解这些区别对于正确决定为 Web 应用程序使用什么内容非常重要。 为了帮助你了解这些差异,我们将首先说明 IIS URL 重写和 ASP.NET 路由的工作原理。

IIS URL 重写

URL 重写的基本思想并不是一个新概念。 大约十年前,它在 Apache Web 服务器中引入。 从那时起,它已被证明是 Web 服务器管理员和 Web 开发人员非常有用的工具。 许多托管在 Apache 上的常用应用程序现在都依赖 URL 重写来支持“干净”URL。

URL 重写的概念很简单。 当客户端向 Web 服务器发送特定 URL 的请求时,URL 重写模块将分析请求的 URL 并将其更改为同一服务器上的其他 URL。 URL 重写模块在请求处理管道中提前运行,在 Web 服务器决定用于处理请求的处理程序之前修改请求的 URL。 根据重写的 URL 选择的处理程序处理请求,并生成一个发回 Web 浏览器的响应。 请求客户端永远不会看到重写的 URL;就客户端而言,它已经接收到来自原始 URL 的响应。

在 IIS 体系结构方面,此过程由下图表示:

Diagram of the I I S U R L Rewriting process from the H T T P Request to the H T T P Response.

URL 重写模块是一个本机代码模块,该模块在“预开始请求”或“开始请求”阶段插入请求处理管道,然后使用一组重写规则评估请求的 URL 路径。 每个重写规则都会分析 URL 路径,如果满足所有规则条件,则会将原始路径更改为新路径。 在评估完所有规则后,URL 重写模块将生成一个最终 URL 路径,该路径用于 IIS 管道处理的剩余部分中的请求。 这意味着,IIS 管道中的处理程序选择是基于 URL 重写模块生成的重写 URL 进行的。

ASP.NET 路由

ASP.NET 路由是一种请求调度机制,允许开发人员将特定 URL 与可以处理向该 URL 发出的请求的处理程序相关联。 这种关联是通过注册“路由”来完成的,这些路由定义了为特定 URL 路径调用哪个处理程序。 当向 Web 服务器发出请求时,ASP.NET 路由会在注册路由列表中查找请求的 URL 路径。 如果找到路由,则会调用该路由的相应处理程序来处理该请求。

在 IIS 和 ASP.NET 体系结构方面,此过程由下图表示:

Diagram of the A S P dot NET routing process using I H T T P Handlers from Request to Response.

ASP.NET 路由作为托管代码模块实现,该模块插入到解析缓存阶段(PostResolveRequestCache 事件)和映射处理程序阶段(PostMapRequestHandler 事件)的 IIS 请求处理管道中。 ASP.NET 路由配置为针对向 Web 应用程序发出的所有请求运行。

在 PostResolveRequestCache 事件期间,模块通过路由表(路由对象的集合)查找与请求的 URL 路径匹配的路由。 如果找到匹配项,该模块将获取对对应于该路由的处理程序的引用,并将引用保存为当前 HTTP 上下文的一部分。 处理程序可以是实现 System.Web.IHttpHandler 接口的任何 .NET Framework 对象。 如果找不到路由,则模块将不执行任何操作,URL 将失败并正常处理(通常通过将其与磁盘上的文件匹配)。

在 PostMapRequestHandler 事件期间,模块检查 HTTP 上下文是否包含有关处理程序的任何信息。 如果这样做,ASP.NET 路由将使用信息来设置当前 HTTP 上下文的 Handler 属性。 这可确保在“执行处理程序”阶段,IIS 将执行路由模块选择的处理程序。 如果未设置该信息,则模块不会执行任何操作,URL 将失败,让 IIS 做出处理程序选择。

IIS URL 重写和 ASP.NET 路由之间的区别

根据上述说明,IIS URL 重写和 ASP.NET 路由之间存在以下主要概念差异:

  1. URL 重写用于在 Web 服务器处理请求之前操作 URL 路径。 URL 重写模块不知道哪个处理程序最终将处理重写的 URL。 此外,实际请求处理程序可能不知道 URL 已被重写。
  2. ASP.NET 路由用于根据请求的 URL 路径将请求调度到处理程序。 与 URL 重写相反,路由模块知道处理程序,并选择应为请求的 URL 生成响应的处理程序。 可以将 ASP.NET 路由视为高级处理程序映射机制。

除了这些概念差异之外,IIS URL 重写和 ASP.NET 路由之间还有以下功能差异:

  1. IIS URL 重写模块可用于任何类型的 Web 应用程序,其中包括 ASP.NET、PHP、ASP 和静态文件。 ASP.NET 路由只能与基于 .NET Framework 的 Web 应用程序一起使用。
  2. 无论应用程序池使用集成 IIS 管道模式还是经典 IIS 管道模式,IIS URL 重写模块都以相同的方式工作。 对于 ASP.NET 路由,最好使用集成管道模式。 ASP.NET 路由可以在经典模式下工作,但在这种情况下,应用程序 URL 必须包含文件扩展名,或者应用程序必须配置为在 IIS 中使用“*”处理程序映射。
  3. IIS URL 重写模块可以根据域名、HTTP 标头和服务器变量做出重写决策。 默认情况下,ASP.NET 路由仅适用于 URL 路径和 HTTP-Method 标头。
  4. 除了重写之外,URL 重写模块还可以执行 HTTP 重定向、发出自定义状态代码和中止请求。 ASP.NET 路由不执行这些任务。
  5. URL 重写模块在其当前版本中不可扩展。 ASP.NET 路由完全可扩展且可自定义。

应使用哪个选项?

如果需要选择一种技术来为 Web 应用程序启用干净 URL,那么所有这些信息意味着什么? 在本部分中,我们将介绍如何做出此选择。

如果使用除 ASP.NET 以外的任何内容生成 Web 应用程序,请使用 IIS URL 重写模块。 否则,规则为:

  1. 如果要开发使用 ASP.NET MVCASP.NET 动态数据技术的新 ASP.NET Web 应用程序,请使用 ASP.NET 路由。 应用程序将受益于对干净 URL 的本机支持,包括为网页中的链接生成干净 URL。 请注意,ASP.NET 路由尚不支持标准 Web Forms 应用程序,尽管将来有计划支持它。
  2. 如果已有旧版 ASP.NET Web 应用程序,并且不想更改它,请使用 URL 重写模块。 URL 重写模块允许将搜索引擎友好的 URL 转换为应用程序当前使用的格式。 此外,它还允许你创建重定向规则,这些规则可用于将搜索引擎爬网程序重定向到干净 URL。

然而,在实践中,选择不一定是非此即彼。 这些技术可以一起使用,并且可以相互补充。 在以下部分中,我们概述了一些方案,你可以在其中结合使用 ASP.NET 路由和 IIS URL 重写。

为应用程序强制实施规范 URL。
应强制使用 http://www.mysite.com/home/about 而不是 http://mysite.com/Home/About。 当 Web 客户端请求不符合所需格式的 URL 时,客户端将重定向到规范 URL。 在此方案中,可以使用 URL 重写模块来强制实施规范 URL 并执行重定向,并使用 ASP.NET 路由来选择将处理请求的 URL 路径的处理程序。

以下示例演示了可用于此方案的 URL 重写规则:

<rewrite>
    <rules>
        <rule name="Enforce canonical hostname" stopProcessing="true">
            <match url="(.*)" />
            <conditions>
                <add input="{HTTP_HOST}" negate="true" pattern="^www\.mysite\.com$" />
            </conditions>
            <action type="Redirect" url="http://www.mysite.com/{R:1}" redirectType="Permanent" />
        </rule>
    </rules>
</rewrite>

从其他站点或服务器提供静态内容。
Web 应用程序部署在多个服务器上,使得动态 Web 内容位于一个站点或服务器上,并且所有静态内容都位于不同的站点或服务器上。 可以将 URL 重写模块与 IIS 应用程序请求路由模块一起使用,将静态文件的所有请求转发到其他服务器,同时为当前服务器中动态网页的所有请求提供服务。 这样,ASP.NET 路由仅用于动态 Web 内容,并且不评估静态内容的任何 URL。

以下示例演示了可用于此方案的 URL 重写规则:

<rewrite>
    <rules>
        <rule name="Forward to static file server">
            <match url="^.+\.(?:jpg|bmp|gif)$" />
            <action type="Rewrite" url="http://static_file_server/{R:0}" />
        </rule>
    </rules>
</rewrite>

静态内容管理
将静态文件或文件夹移动到新位置时,仍可以支持旧 URL,以实现向后兼容性。 事实上,你可能不希望网站访问者知道文件或文件夹已被移动。 在这种情况下,可以使用 URL 重写模块来重写静态文件的路径,而动态 ASP.NET 网页的所有 URL 都由路由模块处理。

以下示例演示了可用于此方案的 URL 重写规则:

<rewrite>
    <rules>
        <rule name="Rewrite to new folder">
            <match url="^Images/(.+)$" />
            <action type="Rewrite" url="NewImages/{R:1}" />
        </rule>
    </rules>
</rewrite>

请求阻止
URL 重写模块可用于根据各种条件阻止某些请求。 例如,可以阻止某些网站爬网程序访问网站上的特定 URL 路径。 这样,禁止的请求甚至不会到达 ASP.NET 路由器,从而减少 Web 服务器上的负载。

以下示例演示了一个 URL 重写规则,可用于阻止不需要的网站爬网程序。 请注意,根据用户代理 HTTP 标头或客户端的 IP 地址阻止特定 URL 路径的请求:

<rewrite>
    <rules>
        <rule name="Block SomeRobot" stopProcessing="true">
            <match url="^folder1/folder2" />
            <conditions logicalGrouping="MatchAny">
                <add input="{USER_AGENT}" pattern="SomeRobot" />
                <add input="{REMOTE_ADDR}" pattern="201\.45\.33\.[0-5]" />
            </conditions>
            <action type="AbortRequest" />
        </rule>
    </rules>
</rewrite>

未来方向

尽管 IIS URL 重写和 ASP.NET 路由具有一些功能重叠,但它们解决了每种技术特有的方案。 因此,这两种技术将作为 IIS 中的独立组件继续存在和发展,并有可能在它们之间进行更紧密的集成。 例如,ASP.NET 路由可以利用 URL 重写模块提供的一些丰富工具。 URL 重写模块可以更好地与 ASP.NET 集成,以提供扩展性来自定义 URL 重写逻辑。

结束语

IIS URL 重写或 ASP.NET 路由都可用于为 Web 应用程序实现 URL 操作方案。 ASP.NET 路由是一种针对 ASP.NET 进行优化的解决方案,因此对于那些从头开始设计 ASP.NET 应用程序并希望拥有干净 URL 结构的 Web 开发人员来说,它可能更可取。 IIS URL 重写是一种通用 URL 操作机制,可应对多种场景。 具体而言,Web 开发人员和 Web 服务器/站点管理员可以使用它为现有 Web 应用程序启用干净 URL,而无需修改应用程序代码。