使用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配置的信息:
生产服务器只允许访问一个共享目录,将网站的所有文件复制到共享目录下即可完成部署,不允许远程登录,因此也就不可能设置生产服务器的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代码。
<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节点中,否则会报错。
{
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;
}
}
}