新版本URL-rewrite module for IIS 7.0的发布了,ASP.NET Routing组件随着.NET Framework 3.5 SP1的发布,并在.NET Framework 4.0 Beta中进一步成熟。作为ASP.NET 开发人员,我们不免会对这两个功能相近的组件抱有许多疑问,诸如“它们有什么异同?”“分别适用于什么环境?”等等。本文旨在描述这两者之间的异同,并为开发人员提供什么时候使用哪一种解决方案的建议。
从表面上看来,这两种技术似乎提供了非常相似的功能:为网站提供用户友好的、搜索引擎友好的Url。然而,在这两种技术在原理上却有着本质的区别,需要深入理解才能在选择应用时做出正确的决策。为了帮助大家理解这两种技术,我们首先从他们的运作原理开始讲起。
本文翻译自IIS官方网站,针对国内惯用的术语进行了部分调整。
URL重写(URL Rewriting)
URL Rewriting已经不是什么新技术了,大约在10年前就已经在Apache服务器上广泛应用。由于它被公认为是web管理员和开发人员的法宝,许多流行的基于Apache的网站都依赖于Url重写来提供“优雅”的Url。
简单的说,URL重写的理念非常简单:当一个客户端向服务端请求一个特定的URL时,URL重写模块会分析所请求的URL并把请求更改,指向同一Web服务器上的另一个URL。在web请求周期中插入URL重写模块(如通过HttpModule)非常简单,所以,它能够在服务器处理请求之前来修改所请求的URL。而服务端的处理程序会根据重写后的URL来生成一个Response到客户端浏览器。由于重写过程发生在服务端,所以客户端浏览器根本看不到重写后的URL,在客户端看来,他所收到的Response来自原来所请求的URL。
在IIS 7.0的架构中,这个过程可以由下图来展示:
微软所提供的URL重写模块(URL-rewrite module)是一个native-code的模块,插入web请求处理过程的Pre-begin Request 或 Begin Request 阶段,然后通过所配置的一系列重写规则来进行URL重写。每一个重写规则对URL进行正则分析,判断是否当前所请求的URL满足重写规则所定义的条件,如果满足,就根据规则将原来的URL重写成一个新的URL。当所有的重写规则都过了一遍之后,URL重写模块会生成一个最终的URL路径,传递给剩余的请求处理过程。也就是说IIS管道中的请求处理程序所处理的是在URL重写模块所写后的URL。
ASP.NET路由(ASP.NET Routing)
从本质上来说,ASP.NET路由是一种请求调度机制,它允许开发者将符合指定规则的URL关联给一个能够处理这个请求的Handler来进行处理。这种关联通过注册定义了URL映射关系的“Routes”来完成。当一个请求到达服务端时,ASP.NET路由模块会查找已经注册的Routes表,如果匹配到了某个Route,那么Route相应的Handler就会被调用来处理这个请求。
在IIS 7.0的架构中,这个过程可以由下图来展示:
ASP.NET路由是由托管代码来实现的,作为插件嵌入到IIS请求处理管道的Resolve Cache步骤(PostResolveRequestCache 事件)和Map Handler 步骤(PostMapRequestHandler)中。ASP.NET路由会被配置为对Web Application全局的请求都生效。
在PostResolveRequestCache事件过程中,路由模块会查找一个路由表(一个route对象的集合),来查找匹配所请求URL的Route。如果找到了匹配的Route,ASP.NET路由模块会获取一个处理这个Route的handler,并把这个handler的引用保存到当前的HttpContext中去。当然,这个handler可以是实现了System.Web.IHttpHandler接口的任何类(比如Page类)。如果没能够找到匹配的Route,那么ASP.NET路由模块就什么也不做,任由这个请求走完剩下的处理过程(通常会映射到一个硬盘文件如XX.aspx)。
在PostMapRequestHandler事件过程中,路由模块会检查当前的HttpContext是否包含一个handler的信息,如果有的话,ASP.NET路由模块就会把当前HttpContext的Handler属性设置成所找到的handler。这样就让IIS在Execute Handler步骤中执行路由模块所选中的handler。如果没有的话,ASP.NET路由模块就什么也不做,让IIS来选择一个handler处理这个URL请求。
URL 重写和ASP.NET 路由的区别
基于上面的说明,我们可以看出,URL重写和ASP.NET路由在概念上的差别有如下几点:
- URL重写用来在Web服务器处理请求之前处理URL。URL重写模块不知道究竟什么handler会被用来处理重写后的URL,相同,这个最终的handler也不知道这个URL是否被重写过了。
- ASP.NET路由用来根据URL来为一个请求指派相应的处理程序(handler),与URL重写相反,路由组件知道相关的handler,并且亲自选择handler来处理所请求的URL。鉴于此点,我们也可以把ASP.NET路由想作是一个高级的处理映射(handler-mapping)机制。
除了概念上的差别,URL重写和ASP.NET路由在功能上也有如下几点差别:
- IIS URL重写模块可以用于任何类型的web应用程序,包括ASP.NET, PHP, ASP甚至静态文件。而ASP.NET路由则只能处理基于.NET Framework的web应用程序。
- IIS URL重写模块在集成(integrated)和经典(classic) IIS管道模式的应用程序池中的运行是一样的。而ASP.NET路由则偏向于应用集成(integrated)管道模式。ASP.NET路由也可以在经典(classic) 模式下运行,但这时程序中的URL必须包含文件扩展名,或者程序在IIS中必须配置一个”*”的handler映射。
- URL重写模块可以通过域名、Http头信息、服务器变量来决定是否进行重写。而默认的情况下,ASP.NET路由只能通过URL路径和Http头信息中的HTTP-Method信息来决定是否进行路由。
- 除了URL重写,IIS URL重写模块还可以来做HTTP跳转、设置自定义的IIS状态代码,甚至终止请求。而ASP.NET路由不能做这些。
- IIS URL重写模块在目前的版本中是不能扩展的,而ASP.NET路由则是完全可扩展、可定制的。
我们该如何选择?
知道了这些异同,我们应该怎样在应用中挑选合适的URL优化方案呢?我们将在下节中来探讨。