用微软组件URLRewriter在Windows Server 2003下实现的在ASP.NET下重写URL

来源:互联网 发布:淘宝卖家如何开通团购 编辑:程序博客网 时间:2024/05/18 13:08

好有成就感的一个晚上啊,虽然困了,也要把晚上的收货整理出来,必须的!
以前粗略的看过一些关于URL重写的文章,大致分为在IIS下、ASP.NET下实现的。还有说在IIS6下不容易实现用ASP.NET重写URL,在IIS7下很容易用ASP.NET实现的。今天通过试验,终于弄清楚其中的奥秘了。
首先在IIS6下不容易截获请求而在IIS7下容易截获请求的说法是错误的,在IIS6下只需要在IIS6的网站属性->主目录->应用程序配置->设置中插入一个“通配符应用程序映射”(C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/aspnet_isapi.dll)。插入这个的作用实际就是:不管是什么类型的文件,比如.html、.asp、.jpg等等,甚至是以/结尾的目录,都发到aspnet_isapi.dll,要由aspnet_isapi.dll来“过目”,如果不做这个配置,那么像.asp可能旧有asp_iisapi.dll来处理了。


这里要确保“确定文件是否存在”处于未选中状态,这样IIS才不会实际去检查文件是否存在,因为重写的URL指向的文件物理上是不存在的。

做了上述配置之后,不管是什么样的URL,都会进入到ASP.NET的处理程序,可以随意重写。

另一个需要注意的问题是,网上有几个不同版本的URL重写方法,给的类也是不同的,配置 web.config的方法也是不同的,所以,千万要弄清,web.config 中的配置很多,不要张冠李戴。

web.config 中需要配置的几个地方列出如下:

  1.    <configSections>
  2.         <section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter"/>
  3.     </configSections>
  4.     <appSettings />
  5.     <connectionStrings>
  1.         <httpModules>
  2.             <add type="URLRewriter.ModuleRewriter, URLRewriter" name="ModuleRewriter"/>
  3.         </httpModules>
  4. <!-- 这里网上的资料都是说:可以配置为http处理模块,也可以配置为处理程序,好像两个只要用一个就可以了,我这里用的是处理模块 -->
  1.     <RewriterConfig>
  2.         <Rules>
  3.             <RewriterRule>
  4.                 <LookFor>(.+)/(.+).html</LookFor>
  5.                 <SendTo>~/$2.aspx</SendTo>
  6.             </RewriterRule>
  7.             <RewriterRule>
  8.                 <LookFor>~/(/d{4})/(/d{2})/(/d{2})/.aspx</LookFor>
  9.                 <SendTo>~/ShowBlogContent.aspx?year=$1&month=$2&day=$3</SendTo>
  10.             </RewriterRule>
  11.         </Rules>
  12.     </RewriterConfig>

最后这部份就是控制重写的,只需要用正则表达式匹配请求url,然后给出新的url就可以,这里可以使用正则表达式中的后向引用。

还有一个问题,就是处理回发。
比如访问一个被重写了的url,而这个url上面有一个窗体,虽然打开窗体的时候,使用的是重写前的url,但是当点击窗体的提交按钮的时候,窗体会被定向到重写后的实际的url去。解决这个问题的办法网上也提供了,而且还有vb版本,和C#版本的。
具体的实现方法就是“利用ASP.NET 2.0控件适配器扩展架构来定制控件的输出”,说白了就是ASP.NET 2.0提供了一个功能,可以手工的改写服务器控件。那么我们可以改写form控件的窗体的action,也就是提交路径的属性,下面给出C#版本,VB版本可以网上搜到。
需要两个文件,分别是:
App_Browsers/Form.browser

  1. <browsers>
  2.     <browser refID="Default">
  3.         <controlAdapters>
  4.             <adapter controlType="System.Web.UI.HtmlControls.HtmlForm"
  5.                      adapterType="FormRewriterControlAdapter" />
  6.         </controlAdapters>
  7.     </browser>
  8. </browsers>

App_Code/FormRewriter.cs

  1. using System.Data;
  2. using System.Configuration;
  3. using System.Web;
  4. using System.Web.Security;
  5. using System.Web.UI;
  6. using System.Web.UI.WebControls;
  7. using System.Web.UI.WebControls.WebParts;
  8. using System.Web.UI.HtmlControls;
  9. /// <summary>
  10. /// FormRewriter 的摘要说明
  11. /// </summary>
  12. public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter
  13. {
  14.     public FormRewriterControlAdapter()
  15.     {
  16.     }
  17.     protected override void Render(HtmlTextWriter writer)
  18.     {
  19.         base.Render(new RewriteFormHtmlTextWriter(writer));
  20.     }
  21. }
  22. public class RewriteFormHtmlTextWriter : HtmlTextWriter
  23. {
  24.     public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
  25.         : base(writer)
  26.     {
  27.         base.InnerWriter = writer.InnerWriter;
  28.     }
  29.     public RewriteFormHtmlTextWriter(System.IO.TextWriter writer)
  30.         : base(writer)
  31.     {
  32.         base.InnerWriter = writer;
  33.     }
  34.     public override void WriteAttribute(string name, string value, bool fEncode)
  35.     {
  36.         //If the attribute we are writing is the "action" attribute, and we are not on a sub-control,   
  37.         //then replace the value to write with the raw URL of the request - which ensures that we'll  
  38.         //preserve the PathInfo value on postback scenarios 
  39.         if (name == "action")
  40.         {
  41.             HttpContext context = HttpContext.Current;
  42.             if (context.Items["ActionAlreadyWritten"] == null)
  43.             {
  44.                 //We will use the Request.RawUrl property within ASP.NET to retrieve the origional   
  45.                 //URL before it was re-written. 
  46.                 value = context.Request.RawUrl;
  47.                 //Indicate that we've already rewritten the &ltform>'s action attribute to prevent  
  48.                 //us from rewriting a sub-control under the &ltform> control  
  49.                 context.Items["ActionAlreadyWritten"] = true;
  50.             }
  51.         }
  52.         base.WriteAttribute(name, value, fEncode);
  53.     }
  54. }

经过这么一番折腾后,URL重写就可以在 Windows Server 2003 + IIS6 + ASP.NET 2.0 下实现了。
不过,事情没那么简单,改写是实现了,那么页面上那么多连接的地址都要手工去修改吗?手工修改后在vs.net 的 ide 里面会不会出问题?
留作以后解答……

微软的URL重写类在这里下载,下载后只需编译里面的URLRewriter类为DLL文件,然后在你的项目中做个引用就可以了。
http://www.microsoft.com/china/msdn/library/webservices/asp.net/URLRewriting.mspx

原创粉丝点击