本文将通过实例比较ASP.NET下的三种典型URL重写方案——ISAPI重写(使用开源组件IIRF),ASP.NET2.0内置的urlMappings和基于自定义HTTPModule的URL重写(使用NBear.Web中的UrlRewriteModule实现),并探讨URL重写中可能遇到的陷阱及处理办法。

下载示例程序源码

需要手动为UrlRewriteSample目录添加一个到http://localhost/UrlRewriteSample的同名虚拟目录,允许匿名访问,并设置目录默认页为default.aspx。

另外,为了启用IIRF的URL重写支持,需要将UrlRewriteSample/bin目录下的IsapiRewrite4.dll添加为IIS默认网站的ISAPI过滤器。

设置重写规则

注意,我们的演示程序中将混合使用三种方式的URL重写,因此,需要为三种实现分别设置一些URL重写规则:

1、IIRF,对于IIRF,对应于IsapiRewrite4.dll,在相同的目录会有一个IsapiRewrite4.ini文件,除了默认的一些设置,我们在文件末尾添加了几条自定义规则如下:

# Custom RewriteRules
RewriteRule  ^/UrlRewriteSample/test(.*).aspx         /UrlRewriteSample/Default.aspx?page=$1
RewriteRule  ^/UrlRewriteSample/folder/(.*).aspx    /UrlRewriteSample/Default.aspx?folder=$1
RewriteRule  ^/UrlRewriteSample/folder/?               /UrlRewriteSample/Default.aspx?folder=default

熟悉正则表达式的朋友应该很容易理解上面这三条规则。

规则一将形如testXXX.aspx这样的页面访问,重写为Default.aspx?page=XXX这样的页面;
规则二将形如folder/XXX.aspx的路径,重写为Default.aspx?folder=XXX这样的页面;
规则三将不带任何文件的folder目录的访问,重写为Default.aspx?folder=default这样的页面。

2、urlMappings是ASP.NET2.0内置支持的URL重写配置块,它应该包含在web.config的<system.web>配置块中。但是,这个内置的URL重写支持不支持正则表达式,因而只能用来实现一对一的路径和页面的重写。urlMappings的配置内容包含在下面的Web.config文件中。

3、NBear.Web.Modules.UrlRewriteModule则是NBear中实现的一个基于HTTPModule的URL重写实现,它允许使用正则表达式来描述重写规则。

ASP.NET2.0下的URL重写<?xml version="1.0"?>
ASP.NET2.0下的URL重写
<configuration>
ASP.NET2.0下的URL重写  
ASP.NET2.0下的URL重写  
<configSections>
ASP.NET2.0下的URL重写    
<section name="UrlRewriteRules" type="NBear.Web.Modules.UrlRewriteRules, NBear.Web"/>
ASP.NET2.0下的URL重写  
</configSections>
ASP.NET2.0下的URL重写  
ASP.NET2.0下的URL重写  
<UrlRewriteRules>
ASP.NET2.0下的URL重写       
<Rule key="^/UrlRewriteSample/sample(.*).aspx" value="/UrlRewriteSample/Default.aspx?page=$1" />
ASP.NET2.0下的URL重写       
<Rule key="^/UrlRewriteSample/section/(.*).aspx" value="/UrlRewriteSample/Default.aspx?section=$1" />
ASP.NET2.0下的URL重写  
</UrlRewriteRules>
ASP.NET2.0下的URL重写
ASP.NET2.0下的URL重写  
<system.web>
ASP.NET2.0下的URL重写
ASP.NET2.0下的URL重写    
<urlMappings enabled="true">
ASP.NET2.0下的URL重写      
<add url="~/buildin/Default.aspx" mappedUrl="~/Default.aspx?buildin=default" />
ASP.NET2.0下的URL重写      
<add url="~/buildin.aspx" mappedUrl="~/Default.aspx?page=buildin" />
ASP.NET2.0下的URL重写      
<add url="~/notexistfolder/buildin.aspx" mappedUrl="~/Default.aspx?page=buildin" />
ASP.NET2.0下的URL重写    
</urlMappings>
ASP.NET2.0下的URL重写    
ASP.NET2.0下的URL重写    
<compilation debug="true">
ASP.NET2.0下的URL重写      
<assemblies/>
ASP.NET2.0下的URL重写    
</compilation>
ASP.NET2.0下的URL重写    
ASP.NET2.0下的URL重写    
<httpModules>
ASP.NET2.0下的URL重写      
<add type="NBear.Web.Modules.UrlRewriteModule, NBear.Web" name="UrlRewriteModule"/>
ASP.NET2.0下的URL重写    
</httpModules>
ASP.NET2.0下的URL重写    
ASP.NET2.0下的URL重写  
</system.web>
ASP.NET2.0下的URL重写  
ASP.NET2.0下的URL重写
</configuration>

注意,代码中包含了urlMappings配置和用于NBear.Web.Modules.UrlRewriteModule重写规则。为了比较着几种重写方案,正则表达式基本上是和前面的IIRF定义中的规则类似的。

页面测试

定义完这些重写规则,我们就可以试着在页面中使用它们了。例如,如果我们写一个测试页面如下:

Default.aspx

>

Default.aspx.cs

ASP.NET2.0下的URL重写public partial class _Default : System.Web.UI.Page 
}

注意,Default.aspx页面会输出当前呈现的实际页面及其QueryString参数。

运行该页面,分别点击页面中的链接,我们会看到,貌似所有的URL重写一切正常。但是,当试着点击页面中的按钮,我们马上会发现,页面postback后,浏览器地址栏中的链接变成了那个被重写后的地址,而不是,原来显示于地址栏的虚拟地址了。这是一个严重的不一致,没道理我点击页面的按钮,在没有跳转到其他页面的情况下,地址栏显示另一个页面地址,不是吗?

要解决这个问题,我们只需要为form添加一个onsubmit事件处理如下:

<form >www.elivn.com

解决的办法,只有使用绝对路径!但是,我们当然不会傻到对每个链接直接使用绝对路径的,呵呵:)

将Default.aspx中的所有相对路径都使用Page.ResolveUrl进行包装如下,在输出页面时就将地址转换为绝对路径,就能解决这个恐怖的相对路径陷阱了。当然,也别忘了加上onsubmit事件处理代码:

Default.aspx

>

好了,再试一试点击页面上的链接和按钮,多点几次,再点,再点。。。

。。。

呼~

终于搞定了吧!^-^

本文将通过实例比较ASP.NET下的三种典型URL重写方案——ISAPI重写(使用开源组件IIRF),ASP.NET2.0内置的urlMappings和基于自定义HTTPModule的URL重写(使用NBear.Web中的UrlRewriteModule实现),并探讨URL重写中可能遇到的陷阱及处理办法。

下载示例程序源码

需要手动为UrlRewriteSample目录添加一个到http://localhost/UrlRewriteSample的同名虚拟目录,允许匿名访问,并设置目录默认页为default.aspx。

另外,为了启用IIRF的URL重写支持,需要将UrlRewriteSample/bin目录下的IsapiRewrite4.dll添加为IIS默认网站的ISAPI过滤器。

设置重写规则

注意,我们的演示程序中将混合使用三种方式的URL重写,因此,需要为三种实现分别设置一些URL重写规则:

1、IIRF,对于IIRF,对应于IsapiRewrite4.dll,在相同的目录会有一个IsapiRewrite4.ini文件,除了默认的一些设置,我们在文件末尾添加了几条自定义规则如下:

# Custom RewriteRules
RewriteRule  ^/UrlRewriteSample/test(.*).aspx         /UrlRewriteSample/Default.aspx?page=$1
RewriteRule  ^/UrlRewriteSample/folder/(.*).aspx    /UrlRewriteSample/Default.aspx?folder=$1
RewriteRule  ^/UrlRewriteSample/folder/?               /UrlRewriteSample/Default.aspx?folder=default

熟悉正则表达式的朋友应该很容易理解上面这三条规则。

规则一将形如testXXX.aspx这样的页面访问,重写为Default.aspx?page=XXX这样的页面;
规则二将形如folder/XXX.aspx的路径,重写为Default.aspx?folder=XXX这样的页面;
规则三将不带任何文件的folder目录的访问,重写为Default.aspx?folder=default这样的页面。

2、urlMappings是ASP.NET2.0内置支持的URL重写配置块,它应该包含在web.config的<system.web>配置块中。但是,这个内置的URL重写支持不支持正则表达式,因而只能用来实现一对一的路径和页面的重写。urlMappings的配置内容包含在下面的Web.config文件中。

3、NBear.Web.Modules.UrlRewriteModule则是NBear中实现的一个基于HTTPModule的URL重写实现,它允许使用正则表达式来描述重写规则。

ASP.NET2.0下的URL重写<?xml version="1.0"?>
ASP.NET2.0下的URL重写
<configuration>
ASP.NET2.0下的URL重写  
ASP.NET2.0下的URL重写  
<configSections>
ASP.NET2.0下的URL重写    
<section name="UrlRewriteRules" type="NBear.Web.Modules.UrlRewriteRules, NBear.Web"/>
ASP.NET2.0下的URL重写  
</configSections>
ASP.NET2.0下的URL重写  
ASP.NET2.0下的URL重写  
<UrlRewriteRules>
ASP.NET2.0下的URL重写       
<Rule key="^/UrlRewriteSample/sample(.*).aspx" value="/UrlRewriteSample/Default.aspx?page=$1" />
ASP.NET2.0下的URL重写       
<Rule key="^/UrlRewriteSample/section/(.*).aspx" value="/UrlRewriteSample/Default.aspx?section=$1" />
ASP.NET2.0下的URL重写  
</UrlRewriteRules>
ASP.NET2.0下的URL重写
ASP.NET2.0下的URL重写  
<system.web>
ASP.NET2.0下的URL重写
ASP.NET2.0下的URL重写    
<urlMappings enabled="true">
ASP.NET2.0下的URL重写      
<add url="~/buildin/Default.aspx" mappedUrl="~/Default.aspx?buildin=default" />
ASP.NET2.0下的URL重写      
<add url="~/buildin.aspx" mappedUrl="~/Default.aspx?page=buildin" />
ASP.NET2.0下的URL重写      
<add url="~/notexistfolder/buildin.aspx" mappedUrl="~/Default.aspx?page=buildin" />
ASP.NET2.0下的URL重写    
</urlMappings>
ASP.NET2.0下的URL重写    
ASP.NET2.0下的URL重写    
<compilation debug="true">
ASP.NET2.0下的URL重写      
<assemblies/>
ASP.NET2.0下的URL重写    
</compilation>
ASP.NET2.0下的URL重写    
ASP.NET2.0下的URL重写    
<httpModules>
ASP.NET2.0下的URL重写      
<add type="NBear.Web.Modules.UrlRewriteModule, NBear.Web" name="UrlRewriteModule"/>
ASP.NET2.0下的URL重写    
</httpModules>
ASP.NET2.0下的URL重写    
ASP.NET2.0下的URL重写  
</system.web>
ASP.NET2.0下的URL重写  
ASP.NET2.0下的URL重写
</configuration>

注意,代码中包含了urlMappings配置和用于NBear.Web.Modules.UrlRewriteModule重写规则。为了比较着几种重写方案,正则表达式基本上是和前面的IIRF定义中的规则类似的。

页面测试

定义完这些重写规则,我们就可以试着在页面中使用它们了。例如,如果我们写一个测试页面如下:

Default.aspx

>

Default.aspx.cs

ASP.NET2.0下的URL重写public partial class _Default : System.Web.UI.Page 
}

注意,Default.aspx页面会输出当前呈现的实际页面及其QueryString参数。

运行该页面,分别点击页面中的链接,我们会看到,貌似所有的URL重写一切正常。但是,当试着点击页面中的按钮,我们马上会发现,页面postback后,浏览器地址栏中的链接变成了那个被重写后的地址,而不是,原来显示于地址栏的虚拟地址了。这是一个严重的不一致,没道理我点击页面的按钮,在没有跳转到其他页面的情况下,地址栏显示另一个页面地址,不是吗?

要解决这个问题,我们只需要为form添加一个onsubmit事件处理如下:

<form >www.elivn.com

解决的办法,只有使用绝对路径!但是,我们当然不会傻到对每个链接直接使用绝对路径的,呵呵:)

将Default.aspx中的所有相对路径都使用Page.ResolveUrl进行包装如下,在输出页面时就将地址转换为绝对路径,就能解决这个恐怖的相对路径陷阱了。当然,也别忘了加上onsubmit事件处理代码:

Default.aspx

>

好了,再试一试点击页面上的链接和按钮,多点几次,再点,再点。。。

。。。

呼~

终于搞定了吧!^-^

相关文章: