要充分理解文章後面談到的話題,我們必須簡單的了解IIS與ASP.NET的溝通過程。我在這裡講解的是IIS 6伺服器。至於IIS 5和IIS 7,前者可以說已經被淘汰了,而後者的「經典模式」與IIS 6可謂如出一轍,而新的「管道模式」其實是講ASP.NET中的某些概念與IIS進行了深度整合。我相信,如果您了解了IIS 6和ASP.NET,在IIS 7的整合模式下也不會有任何問題。
首先我們來看一幅簡單的示意圖,展示了IIS從收到Request開始,到返回Response整個過程中的幾個主要步驟:
在一個ASP.NET應用程式中如果要進行URL Rewrite,那麼一般就是在BeginRequest事件中呼叫HttpContext的RewritePath方法,將該請求重新「定位」至一個目標URL。例如我們就可以在Global.asax中重寫Application_BeginRequest方法來實現這一點:
之所以在BeginRequest中進行Rewrite,是因為這個事件是在所有Pipeline事件中最早被觸發的。在這時進行了重新「定位」之後,目前HttpContext中的一些屬性也發生了相應的變化(例如HttpContext.Request.Path)。這樣,接下來的Pipeline事件的處理程序邏輯就會受到影響。例如需要根據目錄進行權限判斷時,就會使用「定位」後的路徑,而不是ASP.NET所收到的請求。自然最「顯著」的變化就是對Handler的選擇,例如上例,我們把請求重新定位到「CustomerList.aspx」文件,這樣ASP.NET引擎就會選擇*.aspx所對應的System.Web.UI. PageHandlerFactory類別對請求進行處理。
public class Global : System.Web. HttpApplication
{
protected void Application_BeginRequest( object sender, EventArgs e)
{
HttpContext context = HttpContext .Current;
if (context.Request.Path.Equals( "/Customers" ,
StringComparison .InvariantCultureIgnoreCase))
{
context.RewritePath( "~/CustomerList.aspx" );
}
}
}
最後插句提外話,有兩個概念要區分開來,那就是「ASP.NET Pipeline」與「Web Forms」。兩者都是ASP.NET裡的重要模型,但是差異還是非常大的:
其實上面這句話的「形成」二字可能也不太確切。因為Web Forms可能應該是一個可以獨立使用的執行引擎和模型,而System.Web.UI.PageHandlerFactory中也只是利用了這個模型而已。我們在編寫ASP.NET應用程式時,完全可以依照我們的需要,在其他地方使用這個模型。例如在《 技巧:使用User Control做HTML生成》一文中,我們就在一個Generic Handler中把ascx當作模板來產生內容。