[分享]在自定义的HttpHandler中调用.net默认HttpHandler的方法
假如你用自定义HttpHandler的办法将你的网站静态化,也就是在自己的HttpHandler中urlrewrite,你在web.config中的<httpHandlers>节设置了
<add verb="*" path="*.htm" type="MyHttpHandler.HttpHandler,MyHttpHandler"/>
被你静态化为.htm的那些aspx页面比较多而且又没有什么规律,因此你无法在上面的配置中使用正则表达式,可是,你的网站目录同时也存了很多真实存在的.htm文件,你无法在你的HttpHandler中用rewritepath了,因为重写路径后还是本身,这样将导致死循环。可你也不想修改那些.htm文件为别的后缀,怎么办呢。你希望把这些.htm文件交回给.net默认的HttpHandler去处理,传统的方式是建一个HttpHandler工厂,在工厂中先去判断哪些文件需要被重写,就调用自定义的HttpHandler,而不需要重写的则调用.net默认的HttpHandler。但是如果我们需要重写的URL没什么规律,并且又都要用不同的方法重写,那么你得先在HttpHandler工厂里先if..else或switch来执行10几20个枚举判断,然后符合这其中一个的则调用自定义的HttpHandler,到了自定义的HttpHandler里你还得再判断一次,这样使得判断部分的代码重复了,不但容易出错,而且增加了许多麻烦。假如我们能直接在自定义的HttpHandler里判断,不符合的就返回给.net默认HttpHandler来处理。 但是本人找遍了网络都没有找到在自定义的HttpHandler中调用.net默认HttpHandler的方法,甚至csdn上的专家们都说在自定义的HttpHandler无法在返回去调用默认的HttpHandler了。不过,经过本人的研究,找到了一个非常简便的办法。于是分享出来,希望能帮助到后来人。
在自定义的HttpHandler中,先对需要处理的URL做判断,符合的就执行你的重写方法或干其他的事,不符合的,就这样做:
context.Server.Transfer(PageParser.GetCompiledPageInstance(context.Request.Path, context.Request.PhysicalPath, context), true);
原来context.Server.Transfer还提供了一个这样的方法,我用的是.net3.5,2.0没去看,不知道这是不是.net3.5新增的,下面是.net的说明
// 摘要:
// 终止当前页的执行,然后使用一个实现 System.Web.IHttpHandler 接口的自定义 HTTP 处理程序开始新请求的执行,并指定是否要清除
// System.Web.HttpRequest.QueryString 和 System.Web.HttpRequest.Form 集合。
//
// 参数:
// handler:
// 实现 System.Web.IHttpHandler 以便向其传输当前请求的 HTTP 处理程序。
//
// preserveForm:
// 为 true,则保留 System.Web.HttpRequest.QueryString 和 System.Web.HttpRequest.Form
// 集合;为 false,则清除 System.Web.HttpRequest.QueryString 和 System.Web.HttpRequest.Form
// 集合。
//
// 异常:
// System.ApplicationException:
// 当前页请求为回调。
这样,你就可以在自定义的HttpHandler中调用.net默认HttpHandler了,但是光这样还不行,在实际测试的时候会报“没有为扩展名“.htm”注册的生成提供程序”的错误,需要在web.config的compilation节点内增加
<buildProviders>
<add extension=".htm" type="System.Web.Compilation.PageBuildProvider"/>
</buildProviders>
这样就没问题了。不过如果是.js脚本文件,需要先清除.net默认的处理程序,因为.js会被.net认为是j#的后台代码
<buildProviders>
<clear />
<add extension=".js" type="System.Web.Compilation.PageBuildProvider"/>
</buildProviders>
其实,有了这个方法,以后应该可以不需要HttpHandler工厂了,直接在自定义的HttpHandler之间转发就可以了。