天天看點

在ASP.NET中友善重寫URL

經常有人請我指導應該如何動态地重寫URL,以在他們的ASP.NETweb應用中釋出比較幹淨的URL端點這個部落格文章概述了幾個方法,你可以用來在ASP.NET中幹淨地映射或重寫URL,以及按照你自己的需求組織你的URL的結構

為什麼URL映射和重寫很重要?

下面是開發人員想要對URL有更大的靈活性的最常見的場景:

1) 處理這樣的情形:你要更改你的web應用中網頁的結構,但你同時也要確定在你移動網頁後,那些被人收藏的老URL不會成為死連結重寫URL允許你透明地将請求轉交到新的網頁位址而不出錯

2) 在象Google,Yahoo 和 Live 這樣的搜尋引擎中提高你網站上網頁的搜尋相關性具體地來說,URL重寫經常能使你在你網站上網頁的URL裡更加容易地嵌入關鍵詞,這麼做往往會增加别人點選你的連結的機會從使用查詢字元串參數到使用完全限定(fully qualified)的URL也能在某些情形下提高你在搜尋引擎結果中的優先順序使用強制referring連結使用同樣的大小寫(same case)和URL入口(譬如,使用weblogs.asp.net/scottgu 而不是 weblogs.asp.net/scottgu/default.aspx)的技術也能避免因跨越多個URL而造成的網頁排名(pagerank)的降低(avoid diluting your pagerank across multiple URLs),進而增加你的搜尋結果

在一個搜尋引擎日漸驅動網站通路量的世界裡ASP.net 技巧,在你的網頁排名上稍微得到一些提高就能給你的業務帶來不錯的投資回報(ROI)逐漸地,這驅使開發人員使用URL重寫以及其他SEO(搜尋引擎優化 )技術來優化網站(注,SEO是個步調很快的空間,增加你的搜尋相關性的建議月月在演變)想了解一些關于搜尋引擎優化方面好的建議的話ASP.net 技巧,我建議你閱讀一下,以及MarketPosition關于的文章

例程的URL重寫場景

為這個部落格貼子起見,我将假設我們将在一個應用裡建造一套電子商務的産品目錄網頁,産品是按種類來組織的(譬如,圖書ASP.net 技巧,錄像,CD,DVD等等)

讓我們假定一開始我們有個網頁叫Products.aspxASP.net 技巧,通過查詢字元串參數接受一個類别名稱,相應地過濾顯示的産品與這個Products.aspx網頁對應類别的URL看上去象這樣:

但我們不想使用查詢字元串來呈示每個類别,我們想修改應用,讓每個産品類别對搜尋引擎來說看上去象是一個獨特的URLASP.net 技巧,并且在實際的URL中嵌入關鍵詞(而不是通過查詢字元串參數)我們将在這個部落格文章剩下來的篇幅裡,讨論一下達成這個目的我們可以采取的4種不同方法

方法一:使用Request.PathInfo 參數而不是查詢字元串

我将示範的第一個方法根本不使用URL重寫,而是使用ASP.NET中不太為人所知的一個特性,Request的PathInfo屬性為幫助解釋這個屬性的有用之處ASP.net 技巧,考慮一下我們電子商店下面這些URL的情形:

你會在上面這些URL中注意到的一個東西是,他們不再含有查詢字元串值,取而代之的是ASP.net 技巧,類别參數的值是附加到URL上的,是以Products.aspx網頁處理器名稱之後的/參數 值的方式出現的然後,一個自動化的搜尋引擎爬蟲(search engine crawler)會把這些URL解釋成三個不同的URL,而不是一個URL帶有三個不同的輸入值 (搜尋引擎是不理會檔案擴充名的ASP.net 技巧,隻把它當作URL中的另一個字元而已)

你也許很想知道怎麼在ASP.NET中處理這個附加的參數的情形好消息是,這非常簡單隻要使用Request的PathInfo屬性就可以了,該屬性傳回URL中緊随 products.aspx 後面的那部分内容是以ASP.net 技巧,對上面這些URLASP.net 技巧, Request.PathInfo會分别傳回 /Books, /DVDs,和 /CDs(萬一你想知道的話, Request的Path 屬性傳回/products.aspx )

然後,你可以輕易地編寫一個函數來擷取産品類别,象這樣(下面這個函數去除前面的斜杠字元,隻傳回Books,DVDs,或 CDs):

Function GetCategory() (Request.PathInfo.Length = 0) Request.PathInfo.Substring(1

樣例下載下傳:我建立的一個展示這個技術的樣例應用可以在這裡下載下傳這個樣例和這個技術的很好的地方在于,為部署使用這個方法的ASP.NET應用ASP.net 技巧,不需作任何伺服器配置改動在共享主機的環境裡,這個技術也行之有效

方法二:使用HttpModule實作URL重寫

上述Request.PathInfo技術的替換方法是,利用ASP.NET提供的HttpContext.RewritePath方法這個方法允許開發人員動态地重寫收到的URL的處理路徑ASP.net 技巧,然後讓ASP.NET使用剛重寫過後的路徑來繼續執行請求

譬如,我們可以選擇向大衆呈示下列URL:

在外界看來,網站上有三個單獨的網頁(對搜尋爬蟲而言,這看上去很棒)通過使用 HttpContext的RewritePath方法,我們可以在這些請求剛進入伺服器時,動态地把收到的URL重寫成單個Products.aspx網頁接受一個查詢字元串的類别名稱或者PathInfo參數譬如,我們可以使用Global.asax中的Application_BeginRequest事件,來這麼做:

void Application_BeginRequest(object string fullOrigionalpath = Request.Url.ToString()(fullOrigionalpath.Contains("/Products/Books.aspx""/Products.aspx?Category=Books")else if (fullOrigionalpath.Contains("/Products/DVDs.aspx""/Products.aspx?Category=DVDs")

手工編寫象上面這樣的編碼的壞處是,很枯燥乏味,而且容易犯錯我建議你别自己寫,而是使用網上現成的HttpModule來完成這項工作這有幾個你現在就可以下載下傳和使用的免費的HttpModule:

這些子產品允許你用聲明的方式在你應用的web.config檔案裡表達比對規則譬如,在你應用的web.config檔案裡使用UrlRewriter.Net子產品來把上面的那些URL映射到單個Products.aspx頁上,我們隻要把這個web.config檔案添加到我們的應用裡去就可以了(不用任何編碼):

<?xml version="1.0"?>

<configuration>

<configSections>

<section name="rewriter"="false"="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter"configSections><system.web><httpModules>

<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter"/>

</httpModules></system.web>

<rewriter>

<rewrite url="~/products/books.aspx" to="~/products.aspx?category=books"rewrite url="~/products/CDs.aspx" to="~/products.aspx?category=CDs"rewrite url="~/products/DVDs.aspx" to="~/products.aspx?category=DVDs"rewriter></configuration>

上面的HttpModule URL重寫子產品還支援正規表達式和URL模式比對(以避免你在web.config 檔案裡硬寫每個URL)是以,不用寫死類别名稱ASP.net 技巧ASP.net 技巧,你可以象下面這樣重寫比對規則,把類别名稱動态地從任何/products/[類别].aspx組合的URL裡取出來:

<rewriter>

<rewrite url="~/products/(.+).aspx" to="~/products.aspx?category=$1"/>

</rewriter>

這使得你的編碼極其幹淨,并且擴充性非常之好

樣例下載下傳:我建立的一個使用UrlRewriter.Net子產品展示這個技術的樣例應用可以在這裡下載下傳

這個樣例和這個技術的很好的地方在于,為部署使用這個方法的ASP.NET應用,不需作任何伺服器配置改動在設定為中等信任安全等級(medium trust)的共享主機的環境裡,這個技術也行之有效 (隻要把檔案FTP/XCOPY到遠端伺服器就可以了,不需要安裝)

方法三:在IIS7中使用HttpModule 實作無擴充名的URL重寫

上述的HttpModule方法在你要重寫的URL含有.aspx 擴充名或者包含另一個被設定為ASP.NET處理的擴充名的情形下一切都工作你這麼做的話,不需要任何特定的伺服器配置,你隻要把你的應用拷貝到遠端伺服器,它會正常工作的

但有的時候,你要重寫的URL要麼擁有一個不為ASP.NET處理的檔案擴充名(譬如ASP.net 技巧, .jpg, .gif, 或 .htm),要麼根本沒有擴充名譬如,我們也許要把這些URL呈示成公開的産品目錄網頁(注意,它們沒有 .aspx 擴充名):

在 IIS5 和 IIS6 中ASP.net 技巧,使用ASP.NET處理上面這樣的URL不是很容易 IIS 5/6 使得在ISAPI擴充(ASP.NET就是這樣一個擴充)裡非常難以重寫這些類型的URLS你需要做的是使用ISAPI過濾器在IIS請求管道(request pipeline)的較早期實作重寫我将在下面的第四個方法裡示範如何在 IIS5/6 實作這樣的重寫

但好消息是, IIS 7.0使得處理這類情形容易之極你現在可以在 IIS 請求管道的任何地方執行一個HttpModule,這意味着你可以使用上面的URLRewriter 子產品 來處理和重寫無擴充名的URL(甚至是帶有 .asp,.php,或 .jsp 擴充名的URL)下面示範了你在IIS7中該如何配置:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

<configSections>

<section name="rewriter"="false"="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter"configSections><system.web><httpModules>

<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter"httpModules></system.web>

<system.webServer>

<modules runAllManagedModulesForAllRequests="true">

<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule"modules>

<validation validateIntegratedModeConfiguration="false"system.webServer>

<rewriter>

<rewrite url="~/products/(.+)" to="~/products.aspx?category=$1"rewriter>

</configuration>

注意一下<system.webServer>内<modules>部分設定為true的runAllManagedModulesForAllRequests屬性這個屬性確定來自Intelligencia的UrlRewriter.Net子產品(是在IIS7正式釋出前編寫的)ASP.net 技巧ASP.net 技巧,會被調用,有機會重寫到伺服器的所有URL請求(包括檔案夾)上面的web.config檔案非常酷之處在于:

1) 它在任何IIS7機器上都會工作,你不需要管理者在遠端主機上啟用任何東西,它也能在設定為中等信任安全等級(medium trust)的共享主機的環境場景下工作

2) 因為我在<httpModules>和 IIS7 的<modules> 部分同時配置了UrlRewriter,我既能在 VS内置的web伺服器(即Cassini)中,也能在IIS7下使用同樣的URL重寫規則兩者完全支援無擴充名的URL重寫這使得測試和開發非常容易

IIS 7.0 将在今年的晚些時候作為Windows Longhorn伺服器的一部分釋出,将在幾個星期内随Beta3版本的釋出支援go-live許可由于添加到IIS7中的所有的新宿主(hosting)特性ASP.net 技巧,我們預期主機供應商将會非常快地開始積極提供IIS7賬号,這意味着你應該很快就可以開始利用上述的無擴充名的URL重寫支援我們将在 IIS7 RTM 時段裡釋出一個為微軟所支援的URL重寫子產品,該模闆是免費的ASP.net 技巧ASP.net 技巧,你可以在IIS7上使用,并且這子產品将對你web伺服器上的所有内容的進階URL重寫場景提供很好的支援

樣例下載下傳:我建立的一個使用IIS7和UrlRewriter.Net子產品展示無擴充名URL重寫技術的樣例應用可以在這裡下載下傳

方法四:在IIS5和IIS6中使用 ISAPIRewrite 來實作無擴充名的URL重寫

如果你不想等到IIS7出來才利用無擴充名的URL重寫,那麼你最好的措施是使用ISAPI過濾器來重寫URL我知道有2個ISAPI過濾器方案,你也許要去看一下:

我沒親手用過上面的産品,雖然我聽過到對這2個産品的好評Scott Hanselman和 Jeff Atwood 最近都寫了精彩的部落格貼子講述使用這些産品的體驗,同時提供了一些如何在這些産品中配置比對規則的例子Helicon Tech的ISAPI Rewrite的規則使用跟 Apache的mod_rewrite同樣的句法,譬如(取自Jeff的部落格貼子):

一定要去讀一下Scott和Jeff的貼子以了解這些ISAPI 子產品的詳情,以及你都能用它們做些什麼

注:使用ISAPI過濾器的一個壞處是,共享主機環境一般不允許你安裝這樣的元件,是以你要用它們的話,你要麼需要一個專用的虛拟主機伺服器,要麼需要一個專用的主機伺服器但,如果你有一個主機計劃允許你安裝ISAPI的話,這會在IIS5/6下會提供最大的靈活性,讓你過渡到IIS7推出為止

在URL重寫裡處理ASP.NET PostBack

大家在使用ASP.NET和重寫URL時經常遇到的一個疑難雜症跟處理postback場景有關具體地來說,當你在一個網頁上放置一個 <form runat="server"> 控件時,ASP.NET 會自動地預設輸出辨別的action屬性指向目前所在頁面當使用URL重寫時,會出現這樣的問題,<form> 控件顯示的URL不是原先請求的URL(譬如,/products/books)ASP.net 技巧,而是重寫過後的URL(譬如,/products.aspx?category=books)這意味着,當你做一個postback到伺服器時,URL不再是你原先幹淨利落的那個了

在 ASP.NET 1.0 和1.1 中,大家經常訴諸于繼承<form> 控件生成他們自己的控件,來正确地輸出要使用的action屬性雖然這可以工作,但結果有點亂,因為這意味着你需要更新你所有的頁面來使用這個另外的表單控件ASP.net 技巧,而且有時在Visual Studio所見即所得設計器裡也會遇上問題

好消息是,在ASP.NET 2.0中,有個比較幹淨的訣竅你可以用來重寫<form>控件的action屬性具體地來說,你可利用新的ASP.NET 2.0控件擴充卡擴充架構來定制控件的輸出,用你提供的值來覆寫action屬性的值這不要求在你的.aspx頁面裡做任何編碼改動,而隻要在你的/app_browsers檔案夾裡添加一個.browser檔案,注冊使用一個控件适配類即可輸出新的action屬性

你可在這裡檢視一個我建立的樣例實作,其展示了該 它在我上面使用的第一個(Request.PathInfo),第二個方法(UrlRewriter.Net 子產品)中都工作,它使用Request的RawUrl屬性擷取原先沒改寫過的 URL來顯示而在第四個方法(ISAPIRewrite過濾器)中,你可以擷取ISAPI過濾器儲存在Request.ServerVariables["HTTP_X_REWRITE_URL"] 中的原先的URL值

我上面的FormRewriter類實作在标準的ASP.NET和ASP.NET AJAX 1.0網頁上應該都工作(如果你遇上問題的話,告訴我一聲)

正确地處理CSS和圖像引用

不少人在第一次使用URL重寫時,有時會遇上一個疑難雜症,就是他們發現他們的圖像和CSS樣式表引用有時會停止工作這是因為他們在HTML網頁裡有對這些檔案的相對引用,當你開始在應用裡重寫URL時,你需要意識到浏覽器經常會在不同的邏輯層次結構層上(logical hierarchy levels)請求檔案,而不是實際存儲在伺服器上的東西

譬如,如果我們上面的/products.aspx網頁對.aspx 網頁裡的logo.jpg有一個相對引用ASP.net 技巧,但是通過 /products/books.aspx這個URL來請求的,那麼浏覽器在顯示網頁時,将會發出一個對/products/logo.jpg的請求,而不是對/logo.jpg的請求要正确地引用這個檔案,确認你用根目錄限定了(root qualify)CSS和圖像引用(/style.css,而不是 style.css)對于ASP.NET控件,你也可以使用~句法從你應用的根目錄來引用檔案(譬如ASP.net 技巧,<asp:image imageurl="~/images/logo.jpg" runat="server"/>)

希望本文對你有所幫助,

Scott

附注:想學習更多的ASP.NET 2.0技巧和訣竅的話,請檢視一下我的ASP.NET 2.0技巧,訣竅和教程網頁

附注2:特别感謝Scott Hanselman 和Michael K. Campbell在他們的網站測試我的表單控件擴充卡 (Form Control Adapter)

列印 | posted on 2007年3月1日 23:38 | Filed Under [ ASP.NET .NET Tips and Tricks Atlas ] | 收藏本頁 (百度搜藏)(QQ書簽)(Live收藏)(Google書簽)(Yahoo書簽)(新浪ViVi)(搜狐網摘)(365Key網摘)(天極網摘)(博采網摘)(和訊網摘)

回報 IIRF是一款開源的重寫URL過濾器,類似于Apache的URL重寫ASP.net 技巧,基于VC8.0(可以用Visual Studio2005或Visual C 2005 Express)開發它可以運作在IIS5.0+,支援ASP,ASP.NETASP.net 技巧,PHP等許多格式相對比ASP.NET2.0自帶的URL重寫,具有更好的性能和許多我們所需要特性,重要的一點在于:它可以支援無擴充名的URL整體機制差不多,都是通過實作 IHttpModule 接口在 Init 中添加事件處理,但要注意根據應用使用的身份驗證為 Forms 還是 Windows 的不同選擇重寫的發生時機,将處理綁定到 Application 的不同僚件上

.NET 有種擴充名為 .ashx 的新檔案格式,MSDN 的解釋是:An ASP.NET Web Handler File. Web handlers are software modules that handle raw HTTP requests received by ASP.NET.,再多的介紹就沒找到了,但從自動生成的代碼架構感覺上相當于在配置檔案中配置了 .ashx 的自定義的 HttpHandler,在對應的 .ashx 檔案隐藏代碼中實作了 IHttpHandler 接口,現在比較常用的應用是使用它來傳回不需要回發的二進制圖表經常有人請我指導應該如何動态地重寫URL,以在他們的ASP.NETweb應用中釋出比較幹淨的URL端點但我們不想使用查詢字元串來呈示每個類别,我們想修改應用,讓每個産品類别對搜尋引擎來說看上去象是一個獨特的URL,并且在實際的URL中嵌入關鍵詞(而不是通過查詢字元串參數)方法一:使用Request.PathInfo 參數而不是查詢字元串你會在上面這些URL中注意到的一個東西是,他們不再含有查詢字元串值ASP.net 技巧,取而代之的是,類别參數的值是附加到URL上的,是以Products.aspx網頁處理器名稱之後的/參數...有個問題請教一下,如果頁面後面帶的是2個參數,Webconfig裡的這個配置節怎麼寫?如何使用2個參數?

<rewriter>

<rewrite url="~/products/(.+).aspx" to="~/products.aspx?category=$1" />

</rewriter>

原文位址Tip/Trick: Url Rewriting with ASP.NET

原文發表日期 Monday, February 26, 2007 9:27 PM

經常有人請我指導應該如何動态地重寫URL,以在他們的ASP.NETweb應用中釋出比較幹淨的URL端點這個部落格文章概述了幾個方法,你可以用來在ASP.NET中幹淨地映射或重寫URL,以及按照你自己的需求組織你的URL的結構

Beijing 2008 Olympic GamesASP.net 技巧, welcome everyone to participate<RewriterRule>

<LookFor>~/cnNews/toList.(.+)/.(.+)/.aspx</LookFor>

<SendTo>~/cnNews/Default.aspx?nc=$1&page=$2</SendTo>

</RewriterRule>

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/zfrong/archive/2008/11/06/3236824.aspx

繼續閱讀