ISAPI_Rewrite3.1于MVC站点下,在IIS7跳转成功,但在IIS6跳转失败,有后缀URL和有后缀URL处理方式不同。
文章来源:博客园
原创作者:pfdcnblogs
一、问题描述
老商铺使用Asp.NET Form,重构后使用Asp.NET MVC。需要对老商铺的链接进行跳转。
介于老商铺之前已经使用ISAPI_Rewrite3.1做过伪静态处理,跳转规则需要处理两种链接(老商铺的英文拼写是错误的-_-!):
localhost:8008/compayinfo/B5BD5324-D7CD-448A-A499-B01808CCFAB6 localhost:8008/companyinfo.aspx?Uid=B5BD5324-D7CD-448A-A499-B01808CCFAB6
在IIS7下,使用以下跳转规则,没有问题:
RewriteRule ^/compayinfo/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/?$ /Home/Company/$1 [NC] RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$ /Home/Company/$1 [NC]
但是在IIS6下,无法跳转。无奈准备将跳转规则硬编码进MVC路由。
悲催的是,写完代码调试的时候才发现,原来NVC的路由中不允许出现问号:
路由 URL 不能以“/”或“~”字符开头,并且不能包含“?”字符。
本来就觉得硬编码很不爽,现在又发现这种限制,马上回头查找IIS6下跳转失败的原因。
二、查找资料
在baidu了几篇,bing了十几篇,google被重置,后得知:
ASP.NET 4.0在安装的时候,会在IIS6注册一个ISAPI Filter,叫做”aspnet_filter.dll”,ISAPI Filter会先于ISAPI处理程序前执行,它会在所有的的无后缀的URL后面加一串字符“/eurl.axd/GUID”, 同时ASP.NET 4.0还会在IIS默认添加一个请求映射规则“*.axd”,映射到aspnet_isapi.dll。此时,所有的无后缀URL加上“/eurl.axd/GUID”后都会变成带.axd后缀,这样就匹配*.axd的映射规则进行ASP.NET的处理通道。在进入ASP.NET通道后,ASP.NET处理程序会删除掉“/eurl.axd/GUID”,让它还原到无后缀的原始情况,并且不会对后续的请求处理带来任何影响。此时,所有的无后缀请求,就进入了ASP.NET的处理通道中,在默认情况下,ASP.NET4.0的全局的web.config中配置了DefaultHttpHandler来接收无后缀的URL请求,但是我们也可以随意更换默认处理程序(比如ASP.NET MVC处理程序)来处理无后缀的URL请求。
提供的解决方案也无外乎:
修改注册表:
在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\4.0.30319.0(64位:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\4.0.30319.0)下,添加键值名为“EnableExtensionlessUrls” 类型为“DWORD”的键值,并设置值为“0”。然后在cmd中运行“IISRESET”,重启IIS以读取注册表修改后的内容。
注:此项修改就是关闭 ASP.NET 4.0对无扩展URL的处理,若将此项键值设为“1”则开启。
或者使用.NET2的应用程序池,或者自定义一个重写模块。
问题是我连修改IIS的权限都没有,更何况注册表了。自定义重写模块也太麻烦了。
三、尝试解决
经过N多次尝试,推测出请求的处理顺序如下:
对于无后缀URL:compayinfo/B5BD5324-D7CD-448A-A499-B01808CCFAB6
1.首先被aspnet_filter处理为:compayinfo/B5BD5324-D7CD-448A-A499-B01808CCFAB6/eurl.axd/GUID
2.然后进入ISAPI_Rewrite,进行重定向
3.接着根据“*.axd”的映射规则将请求交给aspnet_isapi
4.进而在aspnet_isapi中移除后缀/eurl.axd/GUID
5.最后进行后续处理
可以看出,对于无后缀URL,在进行重定向时,需要处理被添加的后缀:
RewriteRule ^/compayinfo/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(/eurl.axd/.*)$ /Home/Company/$1$2 [NC]
测试成功!立马将该方法应用于有后缀URL,进行尝试,惨遭失败:
RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$ /favicon.ico [NC] RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$ /Home/Company/$1 [NC] RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(/eurl.axd/.*)$ /Home/Company/$1 [NC] RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$ /Home/Company/$1/eurl.axd/ [NC] RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$ /Home/Company/$1/eurl.axd/0 [NC] RewriteRule ^/companyinfo.aspx\?Uid=(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$ /Home/Company/$1/eurl.axd0/ [NC]
第一条成功。
第二条失败,出现IIS404。
第三条失败,出现Asp.NET404,找不到/companyinfo.aspx。
第四条成功,但它匹配到了我的一条路由规则“{controller}/{action}/{Identifie}/{id}”,其中id的值为“eurl.axd”
第五条失败,出现Asp.NET404,找不到/Home/Company/B5BD5324-D7CD-448A-A499-B01808CCFAB6/eurl.axd/0。
第六条失败,出现IIS404。
注:
以上内容编辑于2013-09-24 11:13,但一直放在草稿箱中忘了发布,今天才看到,发布一下。
另外,对于有后缀URL,因时间有限且并不特别需要,后并未深入研究。