使用URLRewriter进行URL重写失效

      运行环境:ASP.NET 2.0 + Windows 2003 SP2
      需求描述:站点中许多菜单都调用了相同的页面,通过URL参数区别不同的功能。目前客户希望进行搜索引擎优化(SEO),需要将站点中所有带参数的URL改为简短易记的形式,如"FinancialStatements.aspx?table=IncomeStatements"改为"Statements_Income.aspx",等等。 
      采用办法:采用微软提供的一个开源类库URLRewriter来进行URL重写,将用户的请求重定向到指定的页面。 
http://www.cnblogs.com/micheng11/archive/2008/07/09/1238756.html
      所遇问题:在开发用的服务器上引入URLRewriter并配置URL重写映射表,网站运行成功,所有期望的URL均可以正常重定向到正确的页面,并且没有出现“无法找到资源”的错误。将网站发布到生产环境后URL重写功能失效,用户所有请求的URL均不能重定向到正确的页面,报“无法找到资源”的错误!以下是web.config中有关URLRewriter配置的信息:
10-14-2009 11-45-00 AM

 10-14-2009 11-37-33 AM
      生产服务器只允许访问一个共享目录,将网站的所有文件复制到共享目录下即可完成部署,不允许远程登录,因此也就不可能设置生产服务器的IIS了。
      起初我以为是映射表错误或配置信息错误,但是仔细检查并核对后该功能仍然没有生效,也没有其它的任何错误信息,仅仅只是“无法找到资源”,非常奇怪!我甚至特意将web.config中的配置信息写错,然后也没有任何反应。我疑心是IIS中将站点的Mapping配置中的“检查文件存在”被勾选了,后来经过确认该选项并没有被选中。Google了很久,后来找到一篇文章说是站点的目录结构可能会影响到web.config文件中HttpModules的执行,因为子目录中的配置文件可能继承了父目录中的配置文件,从而导致HttpModules失效。不幸的是我仍然没有权限去查看生产服务器上网站所在目录的父目录,但有一点是肯定的,那就是本网站在生产服务器上是作为一个现有网站的子网站运行的,并且父站点上存在含有HttpModules的配置文件。
http://www.myspaces.cn/daily/archive/2006/08/24/5050.html
      这些仅仅都是猜测,由于权限的原因,我不能亲自去验证。既然不能直接采用URLRewriter在生产服务器上实现用户的需求,那就只能采用别的办法了。
      另辟蹊径
      URLRewriter是开源的,下载安装后可以直接看到源代码,它采用的是HttpModules的方法来处理用户请求并进行URL重定向的,现在的问题是HttpModules不能工作,那么我只能将目光转向Global.asax了。这里有一篇文章详细讲解了URL重写的原理和实现方法:
http://blog.joycode.com/scottgu/archive/2007/03/01/94004.joy
      我们可以采用Global中的Application_BeginRequest事件来进行URL重定向,不过仍然需要映射表。URLRewriter中已经包含了从web.config中解析映射表的功能,不妨直接用它。这样,我们只需要将原web.config中的<add type="URLRewriter.ModuleRewriter, URLRewriter" name="ModuleRewriter" />一节注释掉即可,然后在Application_BeginRequest事件中编写重定向逻辑。可以直接复制原URLRewriter中ModuleRewriter.cs里的Rewriter方法到Application_BeginRequest。
      有一个问题要注意,原URLRewriter是支持正则表达式判断的,如果你希望站点能支持双向URL改写,则只能改成字符串包含匹配了。
      所谓URL双向改写,是在URL改写的基础上进行的功能扩充,例如用户要访问的真实路径可能是http://localhost/Test.aspx?tab=Performance,经过URL改写后,用户可以通过http://localhost/Test_Performance.aspx来进行访问,但是我们希望当用户用前一个URL访问页面时能自动跳转到后一个地址。这就是URL的反向匹配。支持URL的反向匹配不能采用正则表达式了,于是我们需要将web.config文件中有关URLRewriter的映射表稍微改一下,去掉其中正则表达式的字符。下面给出我用的映射表和Application_BeginRequest代码。

  <RewriterConfig>
    
<Rules>
      
<!-- Rules for CompanyOverview pages display -->
      
<RewriterRule>
        
<LookFor>Overview_Performance.aspx</LookFor>
        
<SendTo>CompanyOverview.aspx?tab=Performance</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>Overview_Outlook.aspx</LookFor>
        
<SendTo>CompanyOverview.aspx?tab=Outlook</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>Overview_Strategy.aspx</LookFor>
        
<SendTo>CompanyOverview.aspx?tab=Strategy</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>Overview_KPI.aspx</LookFor>
        
<SendTo>CompanyOverview.aspx?tab=KeyPerformanceIndicators</SendTo>
      
</RewriterRule>


      
<!-- Rules for FinancialStatements pages display -->
      
<RewriterRule>
        
<LookFor>Statements_Income.aspx</LookFor>
        
<SendTo>FinancialStatements.aspx?table=IncomeStatements</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>Statements_Balance.aspx</LookFor>
        
<SendTo>FinancialStatements.aspx?table=BalanceSheets</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>Statements_CashFlows.aspx</LookFor>
        
<SendTo>FinancialStatements.aspx?table=CashFlows</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>Statements_SegmentRevenues.aspx</LookFor>
        
<SendTo>FinancialStatements.aspx?table=SegmentRevenues</SendTo>
      
</RewriterRule>


      
<!-- Rules for Segment Results pages display -->
      
<RewriterRule>
        
<LookFor>segments_client_Overview.aspx</LookFor>
        
<SendTo>segments_client.aspx?tab=Overview</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_client_Performance.aspx</LookFor>
        
<SendTo>segments_client.aspx?tab=Performance</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_client_Outlook.aspx</LookFor>
        
<SendTo>segments_client.aspx?tab=Outlook</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_client_Strategy.aspx</LookFor>
        
<SendTo>segments_client.aspx?tab=Strategy</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_client_KPI.aspx</LookFor>
        
<SendTo>segments_client.aspx?tab=KeyPerformanceIndicators</SendTo>
      
</RewriterRule>

      
<RewriterRule>
        
<LookFor>segments_Server_Overview.aspx</LookFor>
        
<SendTo>segments_Server.aspx?tab=Overview</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_Server_Performance.aspx</LookFor>
        
<SendTo>segments_Server.aspx?tab=Performance</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_Server_Outlook.aspx</LookFor>
        
<SendTo>segments_Server.aspx?tab=Outlook</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_Server_Strategy.aspx</LookFor>
        
<SendTo>segments_Server.aspx?tab=Strategy</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_Server_KPI.aspx</LookFor>
        
<SendTo>segments_Server.aspx?tab=KeyPerformanceIndicators</SendTo>
      
</RewriterRule>

      
<RewriterRule>
        
<LookFor>segments_edd_Overview.aspx</LookFor>
        
<SendTo>segments_edd.aspx?tab=Overview</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_edd_Performance.aspx</LookFor>
        
<SendTo>segments_edd.aspx?tab=Performance</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_edd_Outlook.aspx</LookFor>
        
<SendTo>segments_edd.aspx?tab=Outlook</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_edd_Strategy.aspx</LookFor>
        
<SendTo>segments_edd.aspx?tab=Strategy</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_edd_KPI.aspx</LookFor>
        
<SendTo>segments_edd.aspx?tab=KeyPerformanceIndicators</SendTo>
      
</RewriterRule>

      
<RewriterRule>
        
<LookFor>segments_mbd_Overview.aspx</LookFor>
        
<SendTo>segments_mbd.aspx?tab=Overview</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_mbd_Performance.aspx</LookFor>
        
<SendTo>segments_mbd.aspx?tab=Performance</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_mbd_Outlook.aspx</LookFor>
        
<SendTo>segments_mbd.aspx?tab=Outlook</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_mbd_Strategy.aspx</LookFor>
        
<SendTo>segments_mbd.aspx?tab=Strategy</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_mbd_KPI.aspx</LookFor>
        
<SendTo>segments_mbd.aspx?tab=KeyPerformanceIndicators</SendTo>
      
</RewriterRule>

      
<RewriterRule>
        
<LookFor>segments_osd.aspx</LookFor>
        
<SendTo>segments_osb.aspx</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_osd_Overview.aspx</LookFor>
        
<SendTo>segments_osb.aspx?tab=Overview</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_osd_Performance.aspx</LookFor>
        
<SendTo>segments_osb.aspx?tab=Performance</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_osd_Outlook.aspx</LookFor>
        
<SendTo>segments_osb.aspx?tab=Outlook</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_osd_Strategy.aspx</LookFor>
        
<SendTo>segments_osb.aspx?tab=Strategy</SendTo>
      
</RewriterRule>
      
<RewriterRule>
        
<LookFor>segments_osd_KPI.aspx</LookFor>
        
<SendTo>segments_osb.aspx?tab=KeyPerformanceIndicators</SendTo>
      
</RewriterRule>
    
</Rules>
  
</RewriterConfig>

      注意,在站点的web.config中添加上述映射表时必须同时添加<section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter"/>到configSections节点中,否则会报错。

void Application_BeginRequest(object sender, EventArgs e)
{
    
string requestedUrl = Request.Url.ToString().ToLower();

    
// get the configuration rules
    URLRewriter.Config.RewriterRuleCollection rules = URLRewriter.Config.RewriterConfiguration.GetConfig().Rules;

    
// iterate through each rule
    for (int i = 0; i < rules.Count; i++)
    {
        
// new url send to.
        if (requestedUrl.Contains(Request.ApplicationPath.ToLower() + "/" + rules[i].LookFor.ToLower()))
        {
            Context.RewritePath(Request.ApplicationPath 
+ "/" + rules[i].SendTo);
            
break;
        }
        
// old url redirect.
        else if (requestedUrl.Contains(Request.ApplicationPath.ToLower() + "/" + rules[i].SendTo.ToLower()))
        {
            Context.Response.Redirect(Request.ApplicationPath 
+ "/" + rules[i].LookFor);
            
break;
        }
    }
}
      当然,如果你直接用URLRewriter能实现URL改写功能则更好,想支持双向匹配的话直接去修改URLRewriter的源代码即可。在这里我是没有找到究竟是什么原因导致了URLRewriter失效,不得已才使用了Global的Application_BeginRequest事件,应当算是一个补救的办法吧!
标签: URLRewriter
posted @ 2009-10-14 13:59 Jaxu 阅读(2165) 评论(23) 编辑 收藏

 回复 引用 查看   
#1楼2009-10-14 14:03 | Jertun      
IIS你没配置吧
 回复 引用 查看   
#2楼[楼主]2009-10-14 14:10 | Jaxu      
@Jertun
你指的IIS需要进行其它什么配置吗?“检查文件存在”这一项已经是去掉的。另外我没有权限去设置生产服务器上的IIS,在这种情况下我只能采用这种办法了。呵呵~
如果你有更好的办法不妨指点一二。

 回复 引用 查看   
#3楼[楼主]2009-10-14 14:12 | Jaxu      
这里有一篇关于HttpModule详细介绍的文章,不错,可以了解下:
http://www.tracefact.net/Asp-Net/Introduction-to-Http-Module.aspx

 回复 引用 查看   
#4楼2009-10-14 14:37 | sun8134      
url重写最好用IIS7自带的URL重写
用其他的,有时候容易出错...

 回复 引用 查看   
#5楼[楼主]2009-10-14 15:24 | Jaxu      
引用sun8134:
url重写最好用IIS7自带的URL重写
用其他的,有时候容易出错...

我也知道IIS 7支持URL重写,问题是生产服务器的操作系统用的是windows 2003sp2,没有iis 7,没办法啊。

 回复 引用   
#6楼2009-10-14 15:43 | mmmmmm[未注册用户]
需要设置isapirewriter
楼主也太强了,写那么多规则,其实整一个正则就完全搞定了

 回复 引用 查看   
#7楼2009-10-14 15:50 | lass_name      
<RewriterRule>
<LookFor>(\S+)_(\d+).html</LookFor>
<SendTo>$1.aspx?id=$2</SendTo>
</RewriterRule>

<RewriterRule>
<LookFor>(\S+).html</LookFor>
<SendTo>$1.aspx</SendTo>
</RewriterRule>

 回复 引用   
#8楼2009-10-14 16:13 | lxiangcn[未注册用户]
这个需要服务器的支持
 回复 引用 查看   
#9楼[楼主]2009-10-14 16:52 | Jaxu      
@mmmmmm
你是说在iis上使用isapi rewriter吗?
我的想法是直接在项目中使用URLRewriter,跟iis没有关系哦。这个能否实现?

 回复 引用 查看   
#10楼[楼主]2009-10-14 16:53 | Jaxu      
引用mmmmmm:
需要设置isapirewriter
楼主也太强了,写那么多规则,其实整一个正则就完全搞定了

规则是写得有点多,我去掉了正则表达式,因为要使用双向匹配。

 回复 引用   
#11楼2009-10-14 16:57 | 啊嘞嘞[未注册用户]
http://www.cnblogs.com/cn795/archive/2009/09/03/1559902.html
 回复 引用 查看   
#12楼[楼主]2009-10-14 17:02 | Jaxu      
@啊嘞嘞
感谢提供帮助。我目前不能设置服务器上的iis,没有权限哦。

我的想法是直接在项目中使用URLRewriter,跟iis没有关系哦
 回复 引用 查看   
#14楼2009-10-14 23:17 | 醉春风      
原来是 想通过 代码直接实现,而不需要设置IIS ?
 回复 引用 查看   
#15楼[楼主]2009-10-14 23:48 | Jaxu      
@lass_name
我知道原有的URLRewriter支持正则匹配,但请注意我这里url中所传的参数并不是数字,而是仅有的几个具有特定意义的字符串,用正则恐怕不太好使。
另外,我想支持双向匹配,如果要使用正则的话改动可能会很大。

 回复 引用 查看   
#16楼[楼主]2009-10-14 23:49 | Jaxu      
@醉春风
通过代码直接实现,不外乎就是使用asp.net的httpmodules和global得application_beginrequest事件,我目前知道的就这两种方法。当然,在页面本身上去做文章也是可以的,不过那就得不偿失了,呵呵~~~~

 回复 引用 查看   
#17楼2009-10-15 09:38 | 重庆加戈      
麻烦请问楼主,那两个图是怎么截取的,用的什么工具?
楼主太强大了,学习一下!
 回复 引用 查看   
#19楼[楼主]2009-10-15 14:36 | Jaxu      
引用重庆加戈:麻烦请问楼主,那两个图是怎么截取的,用的什么工具?

Snagit,你去Google上搜一下,一个专业截图工具,收费软件,需要自己找注册码。

 回复 引用 查看   
#20楼2009-10-15 17:14 | Jertun      
引用Jaxu:
@Jertun
你指的IIS需要进行其它什么配置吗?“检查文件存在”这一项已经是去掉的。另外我没有权限去设置生产服务器上的IIS,在这种情况下我只能采用这种办法了。呵呵~
如果你有更好的办法不妨指点一二。

以前好像弄过
IIS 网站属性 主目录 配置 映射 添加
可执行文件:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
扩展名:.html

 回复 引用 查看   
#21楼2009-10-15 17:40 | 重庆加戈      
@Jaxu
多谢.我下载一个绿色版本的,很好很强大的一个软件.
再次感谢.

 回复 引用 查看   
#22楼[楼主]2009-10-16 15:05 | Jaxu      
引用Jertun:
引用Jaxu:
@Jertun
你指的IIS需要进行其它什么配置吗?“检查文件存在”这一项已经是去掉的。另外我没有权限去设置生产服务器上的IIS,在这种情况下我只能采用这种办法了。呵呵~
如果你有更好的办法不妨指点一二。

以前好像弄过
IIS 网站属性 主目录 配置 映射 添加
可执行文件:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
扩展名:.html

这个方法我知道,我是想问还有没有别的比较好的方法。

 回复 引用 查看   
#23楼2009-10-16 15:08 | Jertun      
引用Jaxu:
引用Jertun:
引用Jaxu:
@Jertun
你指的IIS需要进行其它什么配置吗?“检查文件存在”这一项已经是去掉的。另外我没有权限去设置生产服务器上的IIS,在这种情况下我只能采用这种办法了。呵呵~
如果你有更好的办法不妨指点一二。

以前好像弄过
IIS 网站属性 主目录 配置 映射 添加
可执行文件:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
扩展名:.html

这个方法我知道,我是想问还有没有别的比较好的方法。


崩溃 其他的我就不知道了 反正想这种url重写又没什么意思 也没研究过