ASP.net的地址修正(URLRewriter)實現原理及程式碼範例

來源:互聯網
上載者:User

ASP.net的地址修正(URLRewriter)實現原理及程式碼範例 高露 一、概述 訪問者輸入:http://egojit.cnbolgs.com/default.aspx,實際請求和響應的地址卻是:http://www.cnblogs.com/egojit/default.aspx, 這就是UrlRewrite,除了實現次層網域功能,它在簡化使用者輸入地址、SEO、網站版本迭代更新等多個方面發揮著重要作用。 微軟曾在.net framework 1.1中提供過一個名為URLRewriter的小工具供開發人員輕鬆實現UrlRewrite,為:http://download.microsoft.com/download/0/4/6/0463611e-a3f9-490d-a08c-877a83b797cf/MSDNURLRewriting.msi 本文以URLRewriter為例,在.net framework 2.0的環境下做了小部分最佳化調整,供大家學習和參考,能力有限,不足之處請大家及時指出。本文假設讀者對URLRewriter、ASP.net的 Http管線有一定瞭解,否則請查閱相關資料。 二、配置 URLRewriter在web.config裡通過自訂配置結合Regex來實現URL重寫。 自訂節點的聲明:

自訂節點配置項: ^http://([a-zA-Z0-9]{4,16}).cnblogs.com/default.aspx$/$1/default.aspx^http://www.cnblogs.com/([a-zA-Z0-9]{4,16})/$/test/url.aspx?p=$1如上我配置了兩個規則,以執行個體說明,第一個可將:http://wu-jian.cnblogs.com 重寫到:/wu-jian/default.aspx 第二個可將:http://www.cnblogs.com/wu-jian 重寫到:/test/url.aspx?p=wu-jian 但微軟的URLRewriter LookFor並不支援到網域名稱位置,它只能在根目錄之後做文章,截選了它源碼DEMO中的一段: ~/(\d{4})/(\d{2})/(\d{2})\.aspx~/ShowBlogContent.aspx?year=$1&month=$2&day=$3可以發現,當需要使用次層網域或自訂層級更高的rewrite時,URLRewriter是不支援的,所以在此我將原始碼作了一小部分最佳化,匹配與重寫都使用LookFor和SendTo中的原始運算式,不做任何智能替換與修改。其實很多時候,在微軟的產品中都能發現這種“畫蛇添足”的影子。 關於匹配與替換, 其實就是應用了Regex中的“反向引用”原理,在我的部落格裡有程式碼範例,不熟悉正則的朋友可去瞭解,此處不作詳敘。 三、原始碼分析 對自訂配置進行訪問的類: using System; using System.Configuration; using System.Xml; using System.Xml.Serialization; using System.Xml.XPath; namespace PaoTiao.PTRewriter.Config { ///

/// 實現IConfigurationSectionHandler介面,以對自訂節點進行訪問 ///

public class RewriterConfigSerializerSectionHandler : IConfigurationSectionHandler { ///

/// 該方法無需主動調用 /// 它在ConfigurationManager.GetSection()被調用時根據改配置節聲明中所定義的類名和路徑自動執行個體化配置節處理類 ///

public object Create(object parent, object configContext, System.Xml.XmlNode section) { XmlSerializer ser = new XmlSerializer(typeof(RewriterConfiguration)); return ser.Deserialize(new XmlNodeReader(section)); } }//end class } 之前一直寫WEB程式,很少用到自訂節點,直到一次寫Windows Service用到了app.config,發現要讀取自訂節點,就需要實現IConfigurationSectionHandler介面。 using System; using System.Web; using System.Web.Caching; using System.Configuration; using System.Xml.Serialization; namespace PaoTiao.PTRewriter.Config { [Serializable()] [XmlRoot("RewriterConfig")] public class RewriterConfiguration { private RewriterRuleCollection rules; ///

/// 該方法從web.config中讀取規則集合,並使用了Cache以避免頻繁IO操作 ///

/// public static RewriterConfiguration GetConfig() { //使用緩衝 if (HttpContext.Current.Cache["RewriterConfig"] == null) HttpContext.Current.Cache.Insert("RewriterConfig", ConfigurationManager.GetSection("RewriterConfig")); return (RewriterConfiguration)HttpContext.Current.Cache["RewriterConfig"]; } public RewriterRuleCollection Rules { get { return rules; } set { rules = value; } } }//end class } 我想使用UrlRewrite的網站絕大部分都是面向公眾使用者的,面向公眾使用者就面臨著大的流量和並發,誰也不願意為每個請求去讀取一次web.config吧,那麼在此處使用Cache是明智之舉。另外更換了已到期的ConfigurationSettings.GetConfig()方法為ConfigurationManager.GetSection()方法。 如下兩個類完成類似的Model功能。 using System; using System.Collections; namespace PaoTiao.PTRewriter.Config { ///

/// 規則集合 ///

[Serializable()] public class RewriterRuleCollection : CollectionBase { ///

/// 向集合中添加新規則 ///

///RewriterRule對象 public virtual void Add(RewriterRule r) { this.InnerList.Add(r); } ///

/// 擷取或設定項 ///

public RewriterRule this[int index] { get { return (RewriterRule)this.InnerList[index]; } set { this.InnerList[index] = value; } } }//end class } using System; namespace PaoTiao.PTRewriter.Config { ///

/// 重寫規則的資料對象 ///

[Serializable()] public class RewriterRule { private string mLookFor; private string mSendTo; ///

/// 尋找規則 ///

public string LookFor{ get { return this.mLookFor; } set { this.mLookFor = value; } } ///

/// 重寫規則 ///

public string SendTo{ get { return this.mSendTo; } set { this.mSendTo = value; } } }//end class }//end namespace 使用HttpModule實現地址修正 using System; using System.Web; namespace PaoTiao.PTRewriter { ///

/// 實現IHttpModule的抽象類別 ///

public abstract class BaseModuleRewriter : IHttpModule { public virtual void Dispose() { } public virtual void Init(HttpApplication app) { app.BeginRequest += new EventHandler(this.BaseModuleRewriter_BeginRequest); } protected virtual void BaseModuleRewriter_BeginRequest(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender; Rewrite(app); } ///

/// 地址修正抽象函數 ///

///protected abstract void Rewrite(HttpApplication app); }//end class } 在Http模組中進行核心邏輯處理,原始碼是在AuthorizeRequest事件中,此處我使用了BeginRequest事件。 對抽象方法Rewrite的實現。大家可以發現URL重寫其實就一個核心方法:HttpContext.RewritePath 看看MSDN中對該方法的描述:指定內部重寫路徑,並允許請求的 URL 與資源的內部路徑不同。 using System; using System.Text.RegularExpressions; using System.Configuration; using System.IO; namespace PaoTiao.PTRewriter { public class ModuleRewriter : BaseModuleRewriter { ///

/// 地址修正函數 ///

///protected override void Rewrite(System.Web.HttpApplication app) { //開始追蹤記錄檔 app.Context.Trace.Write("ModuleRewriter", "Entering ModuleRewriter"); //擷取規則集合 Config.RewriterRuleCollection rules = Config.RewriterConfiguration.GetConfig().Rules; for (int i = 0; i < rules.Count; i++) { string lookFor = rules[i].LookFor; Regex reg = new Regex(lookFor, RegexOptions.IgnoreCase); if (reg.IsMatch(app.Request.Url.ToString())) { //擷取目的URL string sendToUrl = reg.Replace(app.Request.Url.ToString(), rules[i].SendTo); //追蹤記錄檔 app.Context.Trace.Write("ModuleRewriter", "Rewriting URL to " + sendToUrl); //地址修正 app.Context.RewritePath(sendToUrl); //Temp code for debug //using (StreamWriter sw = new StreamWriter(@"c:\test\rr.txt", true, System.Text.Encoding.UTF8)) //{ // sw.WriteLine(app.Request.Url.ToString()); // sw.WriteLine("--------------------------------------"); // sw.Close(); //} //退出for迴圈 break; } } //結束追蹤記錄檔 app.Context.Trace.Write("ModuleRewriter", "Exiting ModuleRewriter"); } }//end class } 最後在web.config中註冊自訂的Http模組: 四、應用 回到前面的樣本, http://wu-jian.cnblogs.com --> /wu-jian/default.aspx wu-jian所在的位置為網域名稱首碼,或叫次層網域,這就需要在DNS上做一個 *.cnblogs.com 的泛解析。 第二個樣本是將目錄解析到某一地址:http://www.cnblogs.com/wu-jian --> /test/url.aspx?p=wu-jian 很明顯,這裡的關鍵點在於怎樣讓IIS把這種格式的請求交由.net進程來處理,一旦進入.net framwork,我們就能隨心所欲了。OK,通過如下的操作過程即可: IIS管理-->網站-->屬性-->主目錄標籤-->配置-->萬用字元應用程式對應-->插入 1、選擇 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll 2、不勾選“確認檔案是否存在” 五、總結 關於Url Rewrite的介紹很多,第三方組件也很多,比如isapi rewrite、比如iirf,他們通過IIS底層介面實現所以效率更高,Url Rewriter在.Net進程內實現,也是微軟在Framework1.1時代提供的解決方案,其實這篇文章也是多年前寫的,只是最近準備換用IIRF,看著那些在.Net Framework4.0中提示已到期的方法,不得不感歎時光流水,對以前曾花了時間和精力的東西做個整理和備忘吧,同時希望給有需要的人帶來協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.