自己以前写过一篇URL重写的简易文章(已删除),采用的是继承IHttpModule接口,在web.config里注册一个全局处理模块的方式。
在IIS7及以上版本,该模块可以处理所有的URL请求,但IIS6及以下版本,只能处理注册了ASPNET_ISAPI.DLL的IIS文档映射的文件扩展。
--------分隔----------------
刚开始我使用的是在HttpModule的BeginRequest事件里,分析URL请求后采用 Server.Execute(url) 的方式进行URL重写,但这个方式的缺点很明显,就是必须要搭配 Server.End() 来结束响应,如果没有Server.End() 的话,服务器就有可能产生404错误,或者执行原来URL上的页面。
另外还有一个缺点,就是在BeginRequest事件中无法使用Session,因为在BeginRequest当中,并没有产生页面实例,自然就没有办法构建Session对象。
--------分隔----------------
后来我想用AcquireRequestState事件来处理URL重写,因为AcquireRequestState事件是在页面实例已经构建完成之后执行的事件,可以正常访问Session对象。
不过这个方法依然有一个致命的缺点,那就是如果访问的不是一个有效的,或者说“真实”的路径的话,那么就会引发服务器404错误。
为这个问题,一直头痛了很久。
--------分隔----------------
最后谈一下我现在的解决方案。
因为如果想要访问Session对象,就必须要有一个页面实例,而BeginRequest当中是不存在页面实例的,所以我们可以在WebConfig里再注册一个页面处理类,如 urlrewrite.aspx,指向 urlrewritepage 类。
<add verb="*" path="/rewrite.aspx" type="rewritepage" />
这个类为了实现创建页面对象,必须继承IHttpHandler接口;为了访问Session,还必须继承一个IRequiresSessionState的空接口。
下面,在HttpModule的BeginRequest事件中,先对URL进行简单处理,分析出页面参数,路径信息等一些要用的数据,然后进行URL重写。注意,我在这里用到了一个新的URL重写方法 Context.RewritePath,这个方法除了可以安全的进行URL重写外,还允许对参数和路径进行封装传递,而且不需要Server.End 进行配合。
Context.RewritePath("rewrite.aspx","pathinfo","querystring")
至此,我们将信息已经封装给了rewritepage类,下面的URL重写就可以交给它了。
--------分隔----------------
在HttpHandler接口中,必须实现一个ProcessRequest方法,它是这个页面的唯一入口,由它开始处理页面输出的所有一切工作。
我们可以在ProcessRequest方法中执行PathInfo和QueryString检测,也可以访问Session或Cache。当所有的工作处理完毕后,可以选择是继续执行URL重写,或者是返回一个404错误给客户端。
当然,在这之后的重写,我们依然可以用Context.RewritePath,或者使用Server.Execute|Server.Transfer直接输出一个页面,这一切都取决于你的具体应用了。
--------分隔----------------
没有演示代码,真的。
--------最后再分一隔--------
关于 IHttpModule 和 IHttpHandler 的介绍,请直接谷歌或百度一下,有很多示例的,也比较简单。