天天看點

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

在 ASP.NET 中執行 URL 重寫 釋出日期 : 8/23/2004 | 更新日期 : 8/23/2004

Scott Mitchell

4GuysFromRolla.com

适用範圍:

Microsoft® ASP.NET

摘要

:介紹如何使用 Microsoft ASP.NET 執行動态 URL 重寫。URL 重寫是截取傳入 Web 請求并自動将請求重定向到其他 URL 的過程。讨論實作 URL 重寫的各種技術,并介紹執行 URL 重寫的一些實際情況。

下載下傳本文的源代碼。

本頁内容
【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

引言

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

URL 重寫的常見用法

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

請求到達 IIS 時将會發生什麼情況

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

實作 URL 重寫

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

建構 URL 重寫引擎

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

使用 URL 重寫引擎執行簡單的 URL 重寫

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

建立真正“可删節”的 URL

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

結論

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

參考資料

引言

讓 我們花點時間來看一下網站上的一些 URL。您是否發現一些類似于 http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&type=summary 的 URL?或者,您可能将一系列網頁從一個目錄或網站移動到另一個目錄或網站,結果導緻已将舊 URL 用作書簽的通路者斷開連結。在本文中,我們将了解如何通過将 http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&type=summary 替換為類似于 http://yoursite.com/people/sales/chuck.smith 的網址,使用 URL 重寫将那些冗長的 URL 縮寫為富有意義且容易記憶的 URL。我們還将了解如何将 URL 重寫用于建立智能 404 錯誤。

URL 重寫是截取傳入 Web 請求并自動将請求重定向到其他資源的過程。執行 URL 重寫時,通常會檢查被請求的 URL,并基于 URL 的值将請求重定向到其他 URL。例如,在進行網站重組而将 /people/ 目錄下的所有網頁移動到 /info/employees/ 目錄中時,您可能希望使用 URL 重寫來檢查 Web 請求是否指向了 /people/ 目錄中的檔案。如果請求指向 /people/ 目錄中的檔案,您可能希望自動将請求重定向到 /info/employees/ 目錄中的同一檔案。

使用傳統的 ASP,應用 URL 重寫的唯一方法是編寫 ISAPI 篩選器,或者購買提供 URL 重寫功能的第三方産品。但是,使用 Microsoft® ASP.NET,您可以通過很多方法來輕松地建立您自己的 URL 重寫軟體。本文讨論了可供 ASP.NET 開發人員實作 URL 重寫的各種技術,然後讨論了 URL 重寫的一些實際使用情況。在深入讨論 URL 重寫的技術細節之前,讓我們先看一些可以使用 URL 重寫的日常情景。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

URL 重寫的常見用法

創 建資料驅動的 ASP.NET 網站時,通常會産生一個單個的網頁,該網頁基于查詢字元串參數顯示資料庫資料的子集。例如,在設計電子商務站點時,您的任務之一便是允許使用者浏覽待售産 品。為此,您可以建立一個名為 displayCategory.aspx 的頁面,該頁面将顯示給定類别的産品。可以通過查詢字元串參數來指定要檢視的該類别的産品。也就是說,如果使用者要浏覽待售的 Widget 産品,并且所有 Widget 産品的 CategoryID 均為 5,則使用者可以通路以下網址:http://yousite.com/displayCategory.aspx?CategoryID=5。

建立具有此類 URL 的網站有兩點不足:首先,從最終使用者的角度考慮,URL http://yousite.com/displayCategory.aspx?CategoryID=5 比較雜亂。可用性專家 Jakob Neilsen 建議遵循以下标準來選擇 URL:

  • 簡短。
  • 易于鍵入。
  • 可以看出站點的結構。
  • “可删節”,允許使用者通過删除 URL 的組成部分來浏覽站點。

我 還要增加一條标準,即,URL 應該便于記憶。URL http://yousite.com/displayCategory.aspx?CategoryID=5 不符合 Neilsen 的任何标準,也不容易記住。要求使用者鍵入查詢字元串值将使 URL 的鍵入變得非常困難,并且隻有了解查詢字元串參數的用途及其名稱/值對結構的富有經驗的 Web 開發人員才能夠對 URL 進行“删節”。

較 好的方法是允許使用切合實際且容易記憶的 URL,如 http://yoursite.com/products/Widgets。隻要看一眼 URL,您便可以推斷出将要顯示的内容 -- 有關 Widget 的資訊。此 URL 也很容易記住和共享。我可以告訴我的同僚“請檢視 yoursite.com/products/Widgets,”,她可能無需再次問我 URL 是什麼即可打開該頁面。(嘗試一下,您隻需說出“Amazon.com 頁面”即可!)此 URL 還将顯示出來,并且應該是“可删節”的。也就是說,如果使用者删去 URL 的末端,鍵入 http://yoursite.com/products,他們應該看到所有産品的清單,或者至少應該看到他們可以檢視的所有類别的産品清單。

注意

: 要獲得“可删節”URL 的最好示例,可考慮使用由許多 blog 引擎生成的 URL。要檢視 2004 年 1 月 28 日的文章,使用者可以通路諸如 http://someblog.com/2004/01/28 的 URL。如果該 URL 被删節為 http://someblog.com/2004/01,使用者将看到 2004 年 1 月的所有文章。将該 URL 進一步删節為 http://someblog.com/2004 将顯示 2004 年的所有文章。

除了簡化 URL 之外,URL 重寫還經常用于處理網站重組,以免導緻大量連結斷開或書簽過期。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

請求到達 IIS 時将會發生什麼情況

在 正式研究 URL 如何實作重寫之前,應首先了解 Microsoft® Internet Information Services (IIS) 如何處理傳入請求,這一點非常重要。當請求到達 IIS Web 伺服器時,IIS 檢查被請求檔案的擴充名以确定如何處理該請求。IIS 可以自行處理請求(如 HTML 頁面、圖像以及其他靜态内容),或者将請求路由到 ISAPI 擴充。(ISAPI 擴充是一個處理傳入 Web 請求的非托管編譯類。其任務是生成被請求資源的内容。)

例如,當傳入針對 Info.asp 網頁的請求時,IIS 會将此消息路由到 asp.dll ISAPI 擴充。然後,該 ISAPI 擴充将加載被請求的 ASP 頁面,執行該頁面,并将所呈現的 HTML 傳回給 IIS,然後,IIS 将該 HTML 發送回請求用戶端。對于 ASP.NET 頁面,IIS 會将此消息路由到 aspnet_isapi.dll ISAPI 擴充。然後,aspnet_isapi.dll ISAPI 擴充将處理操作傳遞給托管的 ASP.NET 輔助程序,該輔助程式将處理請求,并傳回 ASP.NET 網頁的呈現 HTML。

您可以自定義 IIS,以指定擴充名與 ISAPI 擴充的映射關系。圖 1 顯示了 Internet Information Services 管理工具的“應用程式配置”對話框。請注意,與 ASP.NET 有關的擴充名(.aspx、ascx、config、asmx、rem、cs、vb 及其他)均已映射到 aspnet_isapi.dll ISAPI 擴充。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter
1.

已配置的檔案擴充名映射

讨論 IIS 如何管理傳入請求稍稍超出了本文範圍。但是可以在 Michele Leroux Bustamante 的文章 Inside IIS and ASP.NET 中找到對此内容的深入讨論。ASP.NET 引擎僅處理那些擴充名已明确映射至 IIS 中的 aspnet_isapi.dll 的傳入 Web 請求,了解這一點非常重要。

使用 ISAPI 篩選器檢查請求

IIS 除了可以将傳入 Web 請求的檔案擴充名映射到相應的 ISAPI 擴充之外,還将執行許多其他任務。例如,IIS 将嘗試對送出請求的使用者進行身份驗證,并确定通過身份驗證的使用者是否有權限通路被請求的檔案。在處理請求的有效期内,IIS 将經曆幾個狀态。在每個狀态下,IIS 都将引發可以使用 ISAPI 篩選器以程式設計方式進行處理的事件。

與 ISAPI 擴充一樣,ISAPI 篩選器是在 Web 伺服器上安裝的非托管代碼塊。ISAPI 擴充被設計為可以響應針對特定檔案類型的請求。另一方面,ISAPI 篩選器還包含可以對 IIS 引發的事件進行響應的代碼。ISAPI 篩選器可以截取甚至修改傳入和傳出的資料。ISAPI 篩選器可以應用于很多方面,包括:

  • 身份驗證和授權。
  • 記錄和監視。
  • HTTP 壓縮。
  • URL 重寫。

雖然 ISAPI 篩選器可用于執行 URL 重寫,但本文将讨論如何使用 ASP.NET 實作 URL 重寫。不過,我們将對使用 ISAPI 篩選器與使用 ASP.NET 中的技術實作 URL 重寫進行權衡。

請求進入 ASP.NET 引擎時将會發生什麼情況

在 ASP.NET 之前,需要使用 ISAPI 篩選器來實作 IIS Web 伺服器上的 URL 重寫。由于 ASP.NET 引擎與 IIS 非常相似,是以可以使用 ASP.NET 進行 URL 重寫。存在相似之處的原因在于 ASP.NET 引擎可以實作以下功能:

  • 在處理請求時可以引發事件。
  • 允許任意數量的 HTTP 子產品處理所引發的事件,這與 IIS 的 ISAPI 篩選器相似。
  • 将呈現被請求資源這項任務委托給 HTTP 處理程式,該處理程式與 IIS 的 ISAPI 擴充相似。

與 IIS 一樣,ASP.NET 引擎在請求的有效期内将會觸發事件,通過發信号來表示其處理過程從一個狀态改變為了另一個狀态。例如,當 ASP.NET 引擎首次響應請求時,

BeginRequest

事件将被觸發。接下來觸發的是

AuthenticateRequest

事件,該事件在已建立使用者辨別時出現。(此外,還有大量的其他事件:

AuthorizeRequest

ResolveRequestCache

EndRequest

,等等。這些事件屬于

System.Web.HttpApplication

類;有關詳細資訊,請參閱位于以下網址的技術文檔:HttpApplication Class Overview。)

正 如上一部分所讨論的,可以建立 ISAPI 篩選器以響應 IIS 引發的事件。同樣,ASP.NET 提供了 HTTP 子產品,該子產品可以響應由 ASP.NET 引擎引發的事件。可以将 ASP.NET Web 應用程式配置為具有多個 HTTP 子產品。對于由 ASP.NET 引擎處理的每個請求,将初始化每個已配置的 HTTP 子產品,并允許将事件處理程式綁定到處理請求期間所引發的事件。請注意,對每個請求均使用了許多内置 HTTP 子產品。其中的一個内置 HTTP 子產品是

FormsAuthenticationModule

,該子產品首先檢查是否使用了窗體身份驗證,如果使用,将檢查是否對使用者進行了身份驗證。如果沒有使用,會自動将使用者重定向到指定的登入頁面。

如 上所述,通過使用 IIS,傳入請求将最終發送給 ISAPI 擴充,而 ISAPI 擴充的任務是傳回特定請求的資料。例如,在請求傳統的 ASP 網頁時,IIS 将請求傳遞給 asp.dll ISAPI 擴充,該擴充的任務是傳回被請求的 ASP 頁面的 HTML 标記。ASP.NET 引擎使用相似的方法。初始化 HTTP 子產品後,ASP.NET 引擎的下一項任務是确定應由哪個 HTTP 處理程式來處理請求。

所 有通過 ASP.NET 引擎傳遞的請求最終都将到達 HTTP 處理程式或 HTTP 處理程式工廠(HTTP 處理程式工廠僅傳回 HTTP 處理程式的執行個體,然後使用該執行個體來處理請求)。最終的 HTTP 處理程式将傳回響應,即呈現被請求的資源。此響應将被發送回 IIS,然後 IIS 将響應傳回給提出請求的使用者。

ASP.NET 包括許多内置的 HTTP 處理程式。例如,

PageHandlerFactory

用于呈現 ASP.NET 網頁。

WebServiceHandlerFactory

用于呈現 ASP.NET Web 服務的響應 SOAP 信封。

TraceHandler

将向

trace.axd

呈現請求的 HTML 标記。

圖 2 描述了如何處理對 ASP.NET 資源的請求。首先,IIS 接收到請求,并将請求排程給 aspnet_isapi.dll。接下來,ASP.NET 引擎對已配置的 HTTP 子產品進行初始化。最後将調用正确的 HTTP 處理程式,并呈現被請求的資源,将所生成的标記傳回給 IIS 和請求用戶端。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter
2.

IIS 和 ASP.NET 正在處理請求

建立和注冊自定義 HTTP 子產品和 HTTP 處理程式

建立自定義 HTTP 子產品和 HTTP 處理程式是相對簡單的任務,包括建立實作正确接口的托管類。HTTP 子產品必須實作

System.Web.IHttpModule

接口,而 HTTP 處理程式和 HTTP 處理程式工廠必須分别實作

System.Web.IHttpHandler

接口和

System.Web.IHttpHandlerFactory

接口。建立 HTTP 處理程式和 HTTP 子產品的細節超出了本文的範圍。要獲得詳細的背景知識,請閱讀 Mansoor Ahmed Siddiqui 的文章 HTTP Handlers and HTTP Modules in ASP.NET。

創 建了自定義 HTTP 子產品或 HTTP 處理程式之後,必須将其注冊到 Web 應用程式。為整個 Web 伺服器注冊 HTTP 子產品和 HTTP 處理程式僅需在 machine.config 檔案中進行簡單的添加即可;而為特定 Web 應用程式注冊 HTTP 子產品或 HTTP 處理程式包括向應用程式的 Web.config 檔案中添加幾行 XML。

特别要說明的是,要将 HTTP 子產品添加到 Web 應用程式,應在 Web.config 的 configuration/system.web 部分添加以下幾行:

<httpModules>
   <add type="type" name="name" />
</httpModules>
      

type 值提供了 HTTP 子產品的程式集和類名稱,而 name 值提供了友好名稱,可以在 Global.asax 檔案中使用此友好名稱來引用 HTTP 子產品。

Web.config 的 configuration/system.web 部分中的 <httpHandlers> 标記對 HTTP 處理程式和 HTTP 處理程式工廠進行了配置,如下所示:

<httpHandlers>
   <add verb="verb" path="path" type="type" />
</httpHandlers>
      

如上所述,對于每個傳入請求,ASP.NET 引擎将确定應使用哪個 HTTP 處理程式來呈現請求。此決定是基于傳入請求的動詞和路徑做出的。動詞将指定所作出的 HTTP 請求的類型(GET 或 POST),而路徑将指定被請求檔案的位置和檔案名。是以,如果我們希望 HTTP 處理程式處理對擴充名為 .scott 的檔案的所有請求(GET 或 POST),可以在 Web.config 檔案中添加下面幾行:

<httpHandlers>
   <add verb="*" path="*.scott" type="type" />
</httpHandlers>
      

其中,type 是 HTTP 處理程式的類型。

注意

:注冊 HTTP 處理程式時,應確定 HTTP 處理程式使用的擴充名已從 IIS 映射到 ASP.NET 引擎,這一點非常重要。也就是說,在本 .scott 示例中,如果 .scott 擴充名沒有從 IIS 映射到 aspnet_isapi.dll ISAPI 擴充,則對檔案 foo.scott 的請求将導緻 IIS 試圖傳回檔案 foo.scott 的内容。為了使 HTTP 處理程式可以處理此請求,必須将 .scott 擴充名映射到 ASP.NET 引擎。然後,ASP.NET 引擎将把請求正确地路由到相應的 HTTP 處理程式。

有關注冊 HTTP 子產品和 HTTP 處理程式的詳細資訊,請務必參考 <httpModules> element documentation 和 <httpHandlers> element documentation。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

實作 URL 重寫

可 以使用 ISAPI 篩選器在 IIS Web 伺服器級别實作 URL 重寫,也可以使用 HTTP 子產品或 HTTP 處理程式在 ASP.NET 級别實作 URL 重寫。本文重點介紹如何使用 ASP.NET 實作 URL 重寫,是以我們将不對使用 ISAPI 篩選器實作 URL 重寫的細節進行深入探讨。但是,有大量的第三方 ISAPI 篩選器可用于 URL 重寫,例如:

  • ISAPI Rewrite
  • IIS Rewrite
  • PageXChanger
  • 還有許多其他的篩選器!

通過

System.Web.HttpContext

類的

RewritePath()

方法,可以在 ASP.NET 級别實作 URL 重寫。

HttpContext

類包含有關特定 HTTP 請求的 HTTP 特定資訊。對于 ASP.NET 引擎收到的每個請求,均為該請求建立一個

HttpContext

執行個體。此類具有如下屬性:

Request

Response

,提供對傳入請求和傳出響應的通路;

Application

Session

,提供對應用程式和會話變量的通路;

User

,提供有關通過了身份驗證的使用者的資訊;其他相關屬性。

使用 Microsoft® .NET Framework Version 1.0,

RewritePath()

方法可以接受單個字元串作為要使用的新路徑。

HttpContext

類的

RewritePath(string)

方法在内部對

Request

對象的

Path

屬性和

QueryString

屬性進行更新。除了

RewritePath(string)

,.NET Framework 1.1 還包括另一種形式的

RewritePath()

方法,此方法可以接受三個字元串輸入參數。此備用重載形式不僅要設定

Request

對象的

Path

屬性和

QueryString

屬性,還要設定内部成員變量,這些變量用于計算

Request

對象的

PhysicalPath

PathInfo

FilePath

屬性值。

要在 ASP.NET 中實作 URL 重寫,需要建立 HTTP 子產品或 HTTP 處理程式,以便完成以下操作:

  1. 檢查被請求的路徑,以确定 URL 是否需要重寫。
  2. 如果需要重寫,通過調用 RewritePath() 方法來重寫路徑。

例 如,假設我們的網站中包含每個員工通過 /info/employee.aspx?empID=employeeID 均可通路的資訊。為了使 URL 可以更多地被“删節”,我們可以決定通過以下位址來通路員工頁面:/people/EmployeeName.aspx。這就是我們要使用 URL 重寫的一個例子。也就是說,在請求 /people/ScottMitchell.aspx 頁面時,我們要重寫該 URL,以便使用 /info/employee.aspx?empID=1001 頁面。

使用 HTTP 子產品執行 URL 重寫

在 ASP.NET 級别執行 URL 重寫時,可以使用 HTTP 子產品或 HTTP 處理程式來執行重寫。使用 HTTP 子產品時,必須決定在請求有效期内的哪個時間點上來檢查 URL 是否需要重寫。乍一看,這似乎可以任意選擇,但決定會以一種明顯而微妙的方式對應用程式産生影響。由于内置 ASP.NET HTTP 子產品使用

Request

對象的屬性執行任務,是以選擇在何處執行重寫非常重要。(如上所述,重寫路徑将改變 Request 對象的屬性值。)下面列出了這些密切相關的内置 HTTP 子產品及其捆綁到的事件:

HTTP 子產品 事件 說明
FormsAuthenticationModule AuthenticateRequest 确定使用者是否通過了窗體身份驗證。如果沒有,使用者将被自動重定向到指定的登入頁面。
FileAuthorizationMoudle AuthorizeRequest 使用 Windows 身份驗證時,此 HTTP 子產品将檢查以確定 Microsoft® Windows® 帳戶對被請求的資源具有足夠的權限。
UrlAuthorizationModule AuthorizeRequest 檢查以確定請求者可以通路指定的 URL。通過 Web.config 檔案中的 <authorization> 和 <location> 元素來指定 URL 授權。

如上所述,

BeginRequest

事件在

AuthenticateRequest

之前觸發,後者在

AuthenticateRequest

之前觸發。

可以執行 URL 重寫的一個安全位置是在

BeginRequest

事件中。也就是說,如果 URL 需要重寫,該操作将在任何一個内置 HTTP 子產品運作後執行。使用窗體身份驗證時,這種方法存在一定的缺陷。如果您以前使用過窗體身份驗證,您會了解當使用者通路受限資源時,他們将被自動重定向到指定 的登入頁面。成功登入後,使用者将被傳回到他們第一次嘗試通路的頁面。

如果在

BeginRequest

AuthenticateRequest

事件中執行 URL 重寫,登入頁面(送出後)将把使用者重定向到重寫後的頁面上。也就是說,假設使用者在其浏覽視窗中鍵入了 /people/ScottMitchell.aspx,此位址将被重寫為 /info/employee.aspx?empID=1001。如果将 Web 應用程式配置為使用窗體身份驗證,當使用者第一次通路 /people/ScottMitchell.aspx 時,首先,URL 将被重寫為 /info/employee.aspx?empID=1001;接下來,

FormsAuthenticationModule

将運作,并将使用者重定向到登入頁面(如果需要)。但是,使用者在成功登入後将被發送到 /info/employee.aspx?empID=1001,因為當

FormsAuthenticationModule

運作後,此 URL 即是請求的 URL。

同樣,在

BeginRequest

AuthenticateRequest

事件中執行重寫時,

UrlAuthorizationModule

看到的将是重寫後的 URL。也就是說,如果您在 Web.config 檔案中使用 <location> 元素來為特定的 URL 指定授權,則必須引用重寫後的 URL。

要解決這些細微問題,您可以決定在

AuthorizeRequest

事件中執行 URL 重寫。此方法解決了 URL 授權和窗體身份驗證的一些問題,但同時也産生了新的問題:檔案授權無法工作。使用 Windows 身份驗證時,

FileAuthorizationModule

将檢查以確定通過身份驗證的使用者具有通路特定 ASP.NET 頁面的相應權限。

假 設一組使用者對 C:/Inetput/wwwroot/info/employee.aspx 沒有 Windows 級别的檔案通路權限,并要嘗試通路 /info/employee.aspx?empID=1001,他們将會收到授權錯誤消息。但是,如果我們将 URL 重寫移到

AuthenticateRequest

事件中,當

FileAuthorizationModule

檢查安全設定時,仍然認為被請求的檔案是 people/ScottMitchell.aspx,因為該 URL 必須被重寫。是以,檔案授權檢查将通過,允許此使用者檢視重寫後的 URL /info/employee.aspx?empID=1001 的内容。

那麼,應該何時在 HTTP 子產品中執行 URL 重寫?這取決于要使用的身份驗證類型。如果不想使用任何身份驗證,則無論 URL 重寫發生在

BeginRequest

AuthenticateRequest

還是

AuthorizeRequest

中都沒有什麼關系。如果要使用窗體身份驗證而不使用 Windows 身份驗證,請将 URL 重寫放在

AuthorizeRequest

事件處理程式中執行。最後,如果要使用 Windows 身份驗證,請在

BeginRequest

AuthenticateRequest

事件進行過程中安排 URL 重寫。

在 HTTP 處理程式中執行 URL 重寫

也可以由 HTTP 處理程式或 HTTP 處理程式工廠執行 URL 重寫。如上所述,HTTP 處理程式是負責生成特定類型請求的内容的類;HTTP 處理程式工廠是負責傳回 HTTP 處理程式執行個體的類,該執行個體可以生成特定類型請求的内容。

在本文中,我們将對如何為 ASP.NET 網頁建立 URL 重寫 HTTP 處理程式工廠進行讨論。HTTP 處理程式工廠必須實作

IHttpHandlerFactory

接口,此接口包括

GetHandler()

方法。初始化相應的 HTTP 子產品後,ASP.NET 引擎将确定為給定的請求調用哪個 HTTP 處理程式或 HTTP 處理程式工廠。如果要調用 HTTP 處理程式工廠,ASP.NET 引擎将為 Web 請求調用傳入

HttpContext

的 HTTP 處理程式工廠的

GetHandler()

方法,以及一些其他資訊。然後,HTTP 處理程式工廠必須傳回一個對象,該對象将實作可以處理請求的

IHttpHandler

要通過 HTTP 程式程式執行 URL 重寫,我們可以建立一個 HTTP 處理程式工廠,該處理程式工廠的

GetHandler()

方法将檢查被請求的路徑,以确定是否需要重寫 URL。如果需要,它可以調用傳入的

HttpContext

對象的

RewritePath()

方法,如前面所讨論的。最後,HTTP 處理程式工廠可以傳回由

System.Web.UI.PageParser

類的

GetCompiledPageInstance()

方法傳回的 HTTP 處理程式。(此技術與内置 ASP.NET 網頁 HTTP 處理程式工廠

PageHandlerFactory

工作時所應用的技術相同。)

由 于所有 HTTP 子產品都将在執行個體化自定義 HTTP 處理程式工廠之前進行初始化,是以,在将 URL 重寫放在事件的後半段時,使用 HTTP 處理程式工廠就會帶來相同的風險,即檔案授權無法工作。是以,如果您依賴于 Windows 身份驗證和檔案授權,您可能希望為 URL 重寫使用 HTTP 子產品方法。

在下一部分中,我們将對建構可重用的 URL 重寫引擎進行讨論。在介紹了 URL 重寫引擎(可通過下載下傳本文的代碼獲得)之後,我們将在剩下的兩個部分中對 URL 重寫的實際使用情況進行介紹。首先,我們将讨論如何使用 URL 重寫引擎,并介紹一個簡單的 URL 重寫示例。接下來,我們将利用重寫引擎的正規表達式功能來提供真正“可删節”的 URL。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

建構 URL 重寫引擎

為了有助于描述如何在 ASP.NET Web 應用程式中實作 URL 重寫,我建立了 URL 重寫引擎。此重寫引擎将提供以下功能:

  • 使用 URL 重寫引擎的 ASP.NET 頁面開發人員可以在 Web.config 檔案中指定重寫規則。
  • 重寫規則可以使用正規表達式來實作功能強大的重寫規則。
  • 可以輕松地将 URL 重寫配置為使用 HTTP 子產品或 HTTP 處理程式。

在本文中,我們将介紹僅使用 HTTP 子產品的 URL 重寫。要檢視如何使用 HTTP 處理程式來執行 URL 重寫,請參考可随本文下載下傳的代碼。

為 URL 重寫引擎指定配置資訊

讓我們先介紹一下 Web.config 檔案中重寫規則的結構。首先,您需要在 Web.config 檔案中指明要使用 HTTP 子產品還是 HTTP 處理程式來執行 URL 重寫。在下載下傳代碼中,Web.config 檔案包含兩個已注釋掉的條目:

<!--
<httpModules>
   <add type="URLRewriter.ModuleRewriter, URLRewriter" 
        name="ModuleRewriter" />
</httpModules>
-->

<!--
<httpHandlers>
   <add verb="*" path="*.aspx" 
        type="URLRewriter.RewriterFactoryHandler, URLRewriter" />
</httpHandlers>
-->
      

注釋掉 <httpModules> 條目,以使用 HTTP 子產品執行重寫;注釋掉 <httpHandlers> 條目,以使用 HTTP 處理程式執行重寫。

除 了指定使用 HTTP 子產品還是 HTTP 處理程式執行重寫外,Web.config 檔案還包含重寫規則:重寫規則由兩個字元串組成:要在被請求的 URL 中查找的模式;要替換此模式的字元串(如果找到)。在 Web.config 檔案中,此資訊是使用以下文法表達的:

<RewriterConfig>
   <Rules>
   <RewriterRule>
      <LookFor>要查找的模式</LookFor>
      <SendTo>要用來替換模式的字元串</SendTo>
   </RewriterRule>
   <RewriterRule>
      <LookFor>要查找的模式</LookFor>
      <SendTo>要用來替換模式的字元串</SendTo>
   </RewriterRule>
   ...
   </Rules>
</RewriterConfig>
      

每個重寫規則均由 <

RewriterRule

> 元素表達。要搜尋的模式由 <

LookFor

> 元素指定,而要替換所找到的模式的字元串将在 <

SentTo

> 元素中輸入。這些重寫規則将從頭到尾進行計算。如果發現與某個規則比對,URL 将被重寫,并且對重寫規則的搜尋将會終止。

在 <

LookFor

> 元素中指定模式時,請注意,要使用正規表達式來執行比對和字元串替換。(稍後,我們将介紹一個真實的示例,說明如何使用正規表達式來搜尋模式。)由于模式 是正規表達式,應確定轉義正規表達式中的任何保留字元。(一些正規表達式保留字元包括:.、?、^、$ 及其他。可以通過在前面加反斜杠(如 /.)對這些字元進行轉義,以比對文字句點。)

使用 HTTP 子產品執行 URL 重寫

建立 HTTP 子產品與建立可以實作

IHttpModule

接口的類一樣簡單。

IHttpModule

接口定義了兩種方法:

  • Init(HttpApplication) 。此方法在初始化 HTTP 子產品後觸發。在此方法中,您将把事件處理程式綁定到相應的 HttpApplication 事件。
  • Dispose() 。當請求已完成并已發送回 IIS 時調用此方法。您應當在此處執行所有最終的清除操作。

為了便于為 URL 重寫建立 HTTP 子產品,我将從建立抽象基類

BaseModuleRewriter

開始介紹。此類将實作

IHttpModule

。在

Init()

事件中,它将

HttpApplication

AuthorizeRequest

事件綁定到

BaseModuleRewriter_AuthorizeRequest

方法。

BaseModuleRewriter_AuthorizeRequest

方法将調用該類傳入被請求的

Path

Rewrite()

方法,以及傳入

Init()

方法的

HttpApplication

對象。

Rewrite()

方法是抽象的,也就是說,在

BaseModuleRewriter

類中,

Rewrite()

方法沒有方法主體;從

BaseModuleRewriter

派生而來的類必須覆寫此方法并提供方法主體。

具有此基類後,隻需建立由

BaseModuleRewriter

派生的類即可,該類可以覆寫

Rewrite()

并在那裡執行 URL 重寫邏輯。下面顯示了

BaseModuleRewriter

的代碼。

public abstract class BaseModuleRewriter : IHttpModule
{
   public virtual void Init(HttpApplication app)
   {
      // 警告!此代碼不适用于 Windows 身份驗證!
      // 如果使用 Windows 身份驗證,
      // 請改為 app.BeginRequest
      app.AuthorizeRequest += new 
         EventHandler(this.BaseModuleRewriter_AuthorizeRequest);
   }

   public virtual void Dispose() {}

   protected virtual void BaseModuleRewriter_AuthorizeRequest(
     object sender, EventArgs e)
   {
      HttpApplication app = (HttpApplication) sender;
      Rewrite(app.Request.Path, app);
   }

   protected abstract void Rewrite(string requestedPath, 
     HttpApplication app);
}
      

請注意,

BaseModuleRewriter

類将在

AuthorizeRequest

事件中執行 URL 重寫。如上所述,如果将 Windows 身份驗證與檔案授權結合使用,您需要對此做出更改,以便可以在

BeginRequest

AuthenticateRequest

事件中執行 URL 重寫。

ModuleRewriter

類擴充了

BaseModuleRewriter

類,并負責執行實際的 URL 重寫。

ModuleRewriter

包含單一覆寫方法(

Rewrite()

),如下所示:

protected override void Rewrite(string requestedPath, 
   System.Web.HttpApplication app)
{
   // 獲得配置規則
   RewriterRuleCollection rules = 
     RewriterConfiguration.GetConfig().Rules;

   // 周遊每個規則...
   for(int i = 0; i < rules.Count; i++)
   {
      // 獲得要查找的模式,并且
      // 解析 Url(轉換為相應的目錄)
      string lookFor = "^" + 
        RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, 
        rules[i].LookFor) + "$";

      // 建立 regex(請注意,已設定 IgnoreCase...)
      Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);

      // 檢視是否找到了比對的規則
      if (re.IsMatch(requestedPath))
      {
         // 找到了比對的規則 -- 進行必要的替換
         string sendToUrl = 
RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, 
            re.Replace(requestedPath, rules[i].SendTo));

         // 重寫 URL
         RewriterUtils.RewriteUrl(app.Context, sendToUrl);
         break;      // 退出 For 循環
      }
   }
}
      
Rewrite()

方法從擷取 Web.config 檔案中的一組重寫規則開始。然後,它将周遊重寫規則,每次周遊一個,對于每個規則,它将擷取規則的

LookFor

屬性,并使用正規表達式來确定是否在被請求的 URL 中找到了比對的規則。

如果找到了比對的規則,将在具有

SendTo

屬性值的被請求路徑上執行正規表達式替換。然後,替換後的 URL 将被傳遞到

RewriterUtils.RewriteUrl()

方法中。

RewriterUtils

是一個 helper 類,此類将提供一對由 URL 重寫 HTTP 子產品和 HTTP 處理程式使用的靜态方法。

RewriterUrl()

方法僅調用

HttpContext

對象的

RewriteUrl()

方法。

注意

:您可能已注意到,執行正規表達式比對和替換時,将調用

RewriterUtils.ResolveUrl()

。此 helper 方法隻替換具有應用程式路徑值的字元串中的所有 ~ 執行個體。

URL 重寫引擎的整個代碼可随本文下載下傳。我們已經介紹了大部分密切相關的元件,但還有一些其他元件(例如,對 Web.config 檔案中 XML 格式的重寫規則進行反序列化以使其成為對象的類),以及用于 URL 重寫的 HTTP 處理程式工廠。本文剩餘的三個部分将對 URL 重寫的實際使用情況進行介紹。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

使用 URL 重寫引擎執行簡單的 URL 重寫

為了實際示範 URL 重寫引擎,我們來建構一個使用簡單 URL 重寫的 ASP.NET Web 應用程式。假設我們所工作的公司通過網絡銷售分類産品。這些産品分為以下幾個類别:

類别 ID 類别名稱
1 飲料
2 調味品
3 糖果
4 奶制品
... ...

假 設我們已建立了名為 ListProductsByCategory.aspx 的 ASP.NET 網頁,該網頁在查詢字元串中接受類别 ID 值,并顯示屬于該類的所有産品。是以,要檢視我們銷售的飲料的使用者可以通路 ListProductsByCategory.aspx?CategoryID=1,而那些要檢視奶制品的使用者可以通路 ListProductsByCategory.aspx?CategoryID=4。此外,還假設我們有一個名為 ListCategories.aspx 的頁面,該頁面列出了待售的所有産品類别。

很顯然,這是一個 URL 重寫事例,因為提供給使用者的 URL 沒有為使用者帶來任何意義,也沒有為他們提供任何“可删節性”。是以,讓我們使用 URL 重寫,以便在使用者通路 /Products/Beverages.aspx 時,他們的 URL 将被重寫為 ListProductsByCategory.aspx?CategoryID=1。我們可以在 Web.config 檔案中使用以下 URL 重寫規則來實作此功能。

<RewriterConfig>
   <Rules>
      <!-- 産品制表者規則 -->
      <RewriterRule>
         <LookFor>~/Products/Beverages/.aspx</LookFor>
         <SendTo>~/ListProductsByCategory.aspx?CategoryID=1</SendTo>
      </RewriterRule>
      <RewriterRule>
   </Rules>
</RewriterConfig>
      

正如您可以看到的,此規則将進行搜尋,以檢視使用者請求的路徑是否為 /Products/Beverages.aspx。如果是,它便将 URL 重寫為 /ListProductsByCategory.aspx?CategoryID=1。

注意

:請注意,<

LookFor

> 元素對 Beverages.aspx 中的句點進行了轉義。這是因為在正規表達式模式中使用了 <

LookFor

> 值,并且句點是正規表達式中的特殊字元,該字元表示“比對任意字元”,例如,與 URL /Products/BeveragesQaspx 比對。通過轉義句點(使用 /.),可以表明我們要比對的是文字句點,而不是任何舊的字元。

有 了此規則之後,當使用者通路 /Products/Beverages.aspx 時,頁面上将顯示待售的飲料。圖 3 顯示了通路 /Products/Beverages.aspx 的浏覽器的快照。請注意,在浏覽器的位址欄中,URL 将讀取 /Products/Beverages.aspx,但使用者實際看到的是 ListProductsByCategory.aspx?CategoryID=1 的内容。(實際上,Web 伺服器上根本不存在 /Products/Beverages.aspx 檔案!)

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

圖 3. 重寫 URL 之後請求類别

與 /Products/Beverages.aspx 相似,下面我們要為其他産品類别添加重寫規則。此操作僅包括在 Web.config 檔案的 <Rules> 元素内添加附加的 <

RewriterRule

> 元素。請參閱下載下傳内容中的 Web.config 檔案,以擷取用于此示範的一組完整的重寫規則。

為 了使 URL 更具可删節性,最好使使用者隻需從 /Products/Beverages.aspx 中删除 Beverages.aspx 即可看到産品類别的清單。乍一看,這可能是一項很普通的任務(隻需添加一個将 /Products/ 映射到 /ListCategories.aspx 的重寫規則即可)。但此操作存在一個微妙之處,即您必須首先建立一個 /Products/ 目錄,并在 /Products/ 目錄中添加一個空的 Default.aspx 檔案。

要了解需要執行這些額外步驟的原因,可以參考前面的内容, 即 URL 重寫引擎位于 ASP.NET 級别上。也就是說,如果 ASP.NET 引擎永遠沒有機會處理請求,URL 重寫引擎就沒有辦法檢測傳入的 URL。而且,請記住,僅當被請求的檔案具有相應的擴充名時,IIS 才會将傳入請求傳遞給 ASP.NET 引擎。是以,如果使用者通路 /Products/,而 IIS 沒有看到任何檔案擴充名,那麼它将檢查目錄,以檢視是否存在這樣一個檔案,即該檔案名為預設檔案名中的一個。(Default.aspx、 Default.htm、Default.asp 等等。“IIS 管理”對話框中“Web 伺服器屬性”對話框的“文檔”頁籤對這些預設檔案名進行了定義。)當然,如果 /Products/ 目錄不存在,IIS 将傳回 HTTP 404 錯誤。

是以,我們需要建立 /Products/ 目錄。另外,我們還需要在此目錄中建立一個檔案 Default.aspx。這樣,當使用者通路 /Products/ 時,IIS 将檢測目錄,檢視是否存在一個名為 Default.aspx 的檔案,然後将處理過程傳遞給 ASP.NET 引擎。然後,URL 重寫器将在重寫 URL 時分解。

建立目錄和 Default.aspx 檔案後,請繼續操作,并向 <

Rules

> 元素中添加以下重寫規則:

<RewriterRule>
   <LookFor>~/Products/Default/.aspx</LookFor>
   <SendTo>~/ListCategories.aspx</SendTo>
</RewriterRule>
      

有了此規則之後,當使用者通路 /Products/ 或 /Products/Default.aspx 時,他們将看到産品類别清單,如圖 4 所示。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter
4.

向 URL 添加“可删節性”

處理回發

如 果要重寫的 URL 中包含一個伺服器端的 Web 窗體并執行回發,則窗體回發後,将使用帶下劃線的 URL。也就是說,如果使用者在浏覽器中輸入 /Products/Beverages.aspx,他們在浏覽器位址欄中看到的将是 /Products/Beverages.aspx,但是他們看到的内容将是 ListProductsByCategory.aspx?CategoryID=1 的内容。如果 ListProductsByCategory.aspx 執行了回發,使用者将被回發到 ListProductsByCategory.aspx?CategoryID=1,而不是 /Products/Beverages.aspx。這樣不會中斷任何内容,但從使用者的角度考慮,如果單擊按鈕時突然看到 URL 更改會使他們感到不安。

出現這種情況的原因是:在呈現 Web 窗體時,它會将其操作屬性直接設定為 Request 對象中檔案路徑的值。當然,在呈現 Web 窗體時,URL 已從 /Products/Beverages.aspx 重寫為 ListProductsByCategory.aspx?CategoryID=1,這表明 Request 對象報告使用者要通路 ListProductsByCategory.aspx?CategoryID=1。隻需使伺服器端窗體不呈現操作屬性即可解決此問題。(預設情況下, 如果窗體不包含操作屬性,浏覽器将會回發。)

不幸的是,Web 窗體不允許您明确指定操作屬性,也不允許您設定某些屬性以禁用操作屬性的呈現。是以,我們必須自己來擴充 System.Web.HtmlControls.HtmlForm 類,覆寫 RenderAttribute() 方法并明确指出它不會呈現操作屬性。

由于繼承功能,我們可以獲得 HtmlForm 類的所有功能,并且隻需添加幾行代碼即可獲得所需的行為。以下顯示了自定義類的完整代碼:

namespace ActionlessForm {
  public class Form : System.Web.UI.HtmlControls.HtmlForm
  {
     protected override void RenderAttributes(HtmlTextWriter writer)
     {
        writer.WriteAttribute("name", this.Name);
        base.Attributes.Remove("name");

        writer.WriteAttribute("method", this.Method);
        base.Attributes.Remove("method");

        this.Attributes.Render(writer);

        base.Attributes.Remove("action");

        if (base.ID != null)
           writer.WriteAttribute("id", base.ClientID);
     }
  }
}
      

已被覆寫的

RenderAttributes()

方法的代碼僅包含

HtmlForm

類的

RenderAttributes()

方法的準确代碼,而不設定操作屬性。(我使用 Lutz Roeder 的 Reflector 來檢視

HtmlForm

類的源代碼。)

建立此類并對其進行編譯之後,要在 ASP.NET Web 應用程式中使用它,應首先将其添加到 Web 應用程式的 References 檔案夾中。然後,要使用它來代替

HtmlForm

類,隻需在 ASP.NET 網頁的頂部添加以下内容即可:

<%@ Register TagPrefix="skm" Namespace="ActionlessForm" 
   Assembly="ActionlessForm" %>
      

然後,将 <form runat="server">(如果有)替換為:

<skm:Form id="Form1" method="post" runat="server">
      

并将右邊的 </form> 标記替換為:

</skm:Form>
      

您可以在 ListProductsByCategory.aspx(包含在本文的下載下傳代碼中)中發現操作中的此自定義 Web Form 類。下載下傳内容中還包含了用于無操作 Web Form 的 Visual Studio .NET 項目。

注意

:如果要重寫的目标 URL 沒有執行回發,則無需使用此自定義 Web Form 類。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

建立真正“可删節”的 URL

前一部分中介紹的簡單 URL 重寫顯示了如何輕松地為 URL 重寫引擎配置新的重寫規則。但在使用正規表達式時,重寫規則的真正功能才會發揮更大作用,本部分将對此進行探讨。

Blog 在當今正變得越來越流行,似乎每個人都擁有自己的 blog。如果您不熟悉 blog:blog 是經常更新的個人頁面,通常作為聯機期刊。大多數 blog 隻記錄每天發生的事情,還有一些 blog 可能關注于特定的主題(例如,電影回顧、體育團隊或計算機技術)。

可以在任何地點 對 blog 進行更新,更新頻率為從每天幾次到每周一次或兩次,具體情況取決于作者。通常,blog 首頁将顯示最近的 10 個條目,但實際上,所有 blog 軟體均提供存檔,通路者可以通過存檔讀取較早的文章。Blog 是用于“可删節”URL 的一個功能強大的應用程式。假設在搜尋 blog 的存檔時,您在 URL /2004/02/14.aspx 上發現了您自己。如果您發現自己在閱讀 2004 年 2 月 14 日的文章,您是否覺得很驚訝?而且,您可能希望檢視 2004 年 2 月的所有文章,在這種情況下,您可以嘗試将 URL 删節為 /2004/02/。要檢視 2004 年的所有文章,您可以嘗試通路 /2004/。

維護 blog 時,最好為通路者提供此級别的 URL“可删節性”。許多 blog 引擎都提供此功能,但我們将讨論如何使用 URL 重寫來實作此功能。

首 先,我們需要一個 ASP.NET 網頁,此頁面将按照日、月或年來顯示 blog 條目。假設我們有一個 ShowBlogContent.aspx 頁面,該頁面的查詢字元串參數為年、月和日。要檢視 2004 年 2 月 14 日的文章,我們可以通路 ShowBlogContent.aspx?year=2004&month=2&day=14。要檢視 2004 年 2 月的所有文章,我們可以通路 ShowBlogContent.aspx?year=2004&month=2。最後,要檢視 2004 年的所有文章,我們可以浏覽到 ShowBlogContent.aspx?year=2004。(可以在本文的下載下傳内容中找到 ShowBlogContent.aspx 的代碼。)

在這種情況下,如果使用者通路 /2004/02/14.aspx,我們需要将 URL 重寫為 ShowBlogContent.aspx?year=2004&month=2&day=14。所有三種情況(URL 指定了年、月和日時;URL 僅指定了年和月時;URL 僅指定了年時)均可使用重寫規則進行處理:

<RewriterConfig>
   <Rules>
      <!-- Blog 内容顯示程式規則 -->
      <RewriterRule>
         <LookFor>~/(/d{4})/(/d{2})/(/d{2})/.aspx</LookFor>
         <SendTo>~/ShowBlogContent.aspx?year=$1&amp;month=$2&amp;day=$3</SendTo>
      </RewriterRule>
      <RewriterRule>
         <LookFor>~/(/d{4})/(/d{2})/Default/.aspx</LookFor>
         <SendTo><![CDATA[~/ShowBlogContent.aspx?year=$1&month=$2]]></SendTo>
      </RewriterRule>
      <RewriterRule>
         <LookFor>~/(/d{4})/Default/.aspx</LookFor>
         <SendTo>~/ShowBlogContent.aspx?year=$1</SendTo>
      </RewriterRule>
   </Rules>
</RewriterConfig>
      

這些重寫規則表明了正規表達式的功能。在第一個規則中,我們使用模式 (/d{4})/(/d{2})/(/d{2})/.aspx 查找 URL。在簡明英語中,它對應了這樣一個字元串:首先是四個數字,後跟一個斜杠,然後是兩個數字,後跟一個斜杠,然後再跟兩個數字,最後是一個 .aspx。每個數字組周圍的括号非常重要,通過它可以在相應的 <

SendTo

> 屬性中引用這些括号内的比對字元。 特别是,我們可以針對第一、第二和第三個括号組分别使用 $1、$2 和 $3 引用回括号内的比對組。

注意

:由于 Web.config 檔案采用 XML 格式,但是必須對元素文字部分中的字元(如 &、< 和 >)進行轉義。在第一個規則的 <

SendTo

> 元素中,& 被轉義為 &amp;。在第二個規則的 <

SendTo

> 中使用了另外一種技術(使用 <

![CDATA[...]]

> 元素),無需對内部的内容進行轉義。可以使用兩種方法中的任何一種,并且都會得到相同的結果。

圖 5、6 和 7 顯示了操作中的 URL 重寫。資料實際上是從我的 blog http://scottonwriting.net/ 中拖過來的。圖 5 中顯示了 2003 年 11 月 7 日的文章;圖 6 中顯示了 2003 年 11 月的所有文章;圖 7 顯示了 2003 年的所有文章。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter
5.

2003 年 11 月 7 日的文章

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter
6.

2003 年 11 月的所有文章

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter
7.

2003 年的所有文章

注意

:URL 重寫引擎在 <

LookFor

> 元素中需要使用正規表達式模式。如果您對正規表達式不熟悉,可以閱讀我在早些時候編寫的一篇文章 An Introduction to Regular Expressions。另外,還有一個很好的網站:RegExLib.com,在那裡您可以擷取有關常用正規表達式的幫助資訊,還可以共享您自己的自定義正規表達式。

建構必備的目錄結構

當 請求 /2004/03/19.aspx 時,IIS 将通知 .aspx 擴充,并将請求路由到 ASP.NET 引擎。請求在 ASP.NET 引擎的管道中移動時,URL 将被重寫為 ShowBlogContent.aspx?year=2004&month=03&day=19,并且通路者會看到 2004 年 3 月 19 日的 blog 條目。但是當使用者浏覽到 /2004/03/ 時将會發生什麼情況呢?除非有一個 /2004/03/ 目錄,否則 IIS 将傳回一個 404 錯誤。此外,此目錄中還需要具有 Default.aspx 頁面,以便可以将請求傳遞給 ASP.NET 引擎。

因 此,要使用這種方法,必須手動建立一個用于每年的目錄(其中包含 blog 條目),并且目錄中具有一個 Default.aspx 頁面。另外,在每年目錄中,您需要再手動建立十二個目錄(01、02、?、?...、12),并且每個目錄中均有一個 Default.aspx 檔案。(如上所述,我們還必須執行前面示範中的操作,即在 /Products/ 目錄中添加一個 Default.aspx 檔案,以便通路 /Products/ 時可以正确顯示 ListCategories.aspx。)

很顯然,添加這樣一個目錄結構可能是一件很痛苦的事 情。解決此問題的方法是使所有傳入的 IIS 請求都映射到 ASP.NET 引擎。通過這種方法,即使通路 URL /2004/03/,IIS 也會如實地将請求傳遞給 ASP.NET 引擎(即使并不存在 /2004/03/ 目錄)。但是,使用這種方法将使 ASP.NET 引擎負責處理到達 Web 伺服器的所有類型的傳入請求,包括圖像、CSS 檔案、外部 JavaScript 檔案、Macromedia Flash 檔案,等等。

對處理所有檔案類型的全面讨論遠遠超出了本文的範圍。有關使用此技術的 ASP.NET Web 應用程式的示例,請參閱 .Text,一個開放源 blog 引擎。.Text 可以配置為将所有請求均映射到 ASP.NET 引擎。它可以使用自定義 HTTP 處理程式來處理生成所有檔案類型的問題,自定義 HTTP 處理程式了解如何生成典型的靜态檔案類型(圖像、CSS 檔案,等等)。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

結論

在本文中,我們讨論了如何在 ASP.NET 級别通過

HttpContext

類的

RewriteUrl()

方法來執行 URL 重寫。正如我們所看到的,

RewriteUrl()

更新了特定的

HttpContext's Request

屬性,進而更新了被請求的檔案和路徑。最終結果是,從使用者角度來看,他們要通路某個特定的 URL,但從 Web 伺服器端來看,被請求的卻是另一個 URL。

可以在 HTTP 子產品或 HTTP 處理程式中重寫 URL。在本文中,我們介紹了如何使用 HTTP 子產品執行重寫,并讨論了在管道中的不同階段執行重寫的結果。

當 然,如果執行 ASP.NET 級别的重寫,則僅當已成功地将請求從 IIS 傳遞給 ASP.NET 引擎後才會發生 URL 重寫。實際上,隻有使用者請求帶 .aspx 擴充名的頁面時才會出現這種情況。但是,如果您要使使用者可以進入實際并不存在的 URL,但又希望重寫到現有的 ASP.NET 頁面,則必須建立虛拟目錄和 Default.aspx 頁面,或者對 IIS 進行配置,以使所有傳入請求一律被路由到 ASP.NET 引擎。

【微軟官方】在 ASP.NET 中執行 URL 重寫rewriter

傳回頁首

參考資料

ASP.NET:Tips, Tutorials, and Code

Microsoft ASP.NET Coding Strategies with the Microsoft ASP.NET Team

Essential ASP.NET with Examples in C#

參考資料

URL 重寫是涉及到 ASP.NET 和競争伺服器端 Web 技術的一個主題。例如,Apache Web 伺服器提供了名為 mod_rewrite 的 URL 重寫子產品。Mod_rewrite 是一個功能強大的重寫引擎,提供了基于條件(如 HTTP 标題和伺服器變量)的重寫規則以及使用正規表達式的重寫規則。有關 mod_rewrite 的詳細資訊,請查閱 A User's Guide to URL Rewriting with the Apache Web Server。

還有許多有關使用 ASP.NET 執行 URL 重寫的文章。Rewrite.NET - A URL Rewriting Engine for .NET 對建立模拟 mod_rewrite 正規表達式規則的 URL 重寫引擎進行了介紹。URL Rewriting With ASP.NET 為 ASP.NET 的 URL 重寫功能提供了很好的概述。Ian Griffiths 包含一個 blog entry,介紹了有關使用 ASP.NET 進行 URL 重寫的一些注意事項(如在本文中讨論過的回發問題)。Fabrice Marguerie (read more) 和 Jason Salas (read more) 具有有關使用 URL 重寫來增強搜尋引擎定位功能的 blog 條目。

作者簡介

Scott Mitchell 著有五本書,他還是 4GuysFromRolla.com 網站的建立者。在過去五年中,他一直從事 Microsoft Web 技術方面的研究工作。Scott 是一位獨立的顧問、教育訓練師和作家。您可以通過 [email protected] 與作者進行聯絡,或者通過作者的 blog 進行聯絡,其網址是:http://scottonwriting.net/。

繼續閱讀