• 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 屬性,並使用Regex來確定是否在被請求的 URL 中找到了匹配的規則。
如果找到了匹配的規則,將在具有 SendTo 屬性值的被請求路徑上執行Regex替換。然後,替換後的 URL 將被傳遞到 RewriterUtils.RewriteUrl() 方法中。RewriterUtils 是一個 helper 類,此類將提供一對由 URL 重寫 HTTP 模組和 HTTP 處理常式使用的靜態方法。RewriterUrl() 方法僅調用 HttpContext 對象的 RewriteUrl() 方法。
注意:您可能已注意到,執行Regex匹配和替換時,將調用 RewriterUtils.ResolveUrl()。此 helper 方法只替換具有應用程式路徑值的字串中的所有 ~ 執行個體。
URL 重寫引擎的整個代碼可隨本文下載。我們已經介紹了大部分密切相關的組件,但還有一些其他組件(例如,對 Web.config 檔案中 XML 格式的重寫規則進行還原序列化以使其成為對象的類),以及用於 URL 重寫的 HTTP 處理常式工廠。本文剩餘的三個部分將對 URL 重寫的實際使用方式進行介紹。
返回頁首
使用 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 重寫規則來實現此功能。