不使用特殊方法來處理請求生命周期事件 HttpApplication 類是全局應用類的基類,定義了可以直接使用的一般 C# 事件。那麼使用標準 C# 事件還是特殊方法那就是個人偏好的問題了,如果喜歡,也可以將這兩種方式混合起來使用。 1 using System; 2 using System.Co
不使用特殊方法來處理請求生命周期事件
HttpApplication 類是全局應用類的基類,定義了可以直接使用的一般 C# 事件。那麼使用標準 C# 事件還是特殊方法那就是個人偏好的問題了,如果喜歡,也可以將這兩種方式混合起來使用。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 8 namespace SimpleApp 9 { 10 public class MvcApplication : System.Web.HttpApplication 11 { 12 public MvcApplication() 13 { 14 BeginRequest += (src, args) => RecordEvent("BeginRequest"); 15 AuthenticateRequest += (src, args) => RecordEvent("AuthenticateRequest"); 16 PostAuthenticateRequest += (src, args) => RecordEvent("PostAuthenticateRequest"); 17 } 18 19 protected void Application_Start() 20 { 21 AreaRegistration.RegisterAllAreas(); 22 RouteConfig.RegisterRoutes(RouteTable.Routes); 23 } 24 25 private void RecordEvent(string name) 26 { 27 List<string> eventList = Application["events"] as List<string>; 28 if (eventList == null) 29 { 30 Application["events"] = eventList = new List<string>(); 31 } 32 eventList.Add(name); 33 } 34 } 35 }View Code
我們已經在 MvcApplication 類中添加了一個構造器,併為其中三個請求生命周期事件建立事件處理器。而這三個事件我都使用了 lambda 表達式來調用 RecordEvent 方法,存儲事件的名稱供 controller 來讀取,與之前的例子一樣。
提示:沒有標準的 C# 事件來代替 Application_Start 和 Application_End 方法。我們僅能夠通過特殊方法來接收這兩個通知。
使用單個方法處理多個事件
如果我們想要使用一個方法來處理多個生命周期事件而不依賴 lambda 表達式,那麼 System.Web.HttpContext 類中定義的兩個屬性可以幫助我們。HttpContext 類中提供了當前請求和應用狀態的詳細信息,我們會在後面詳細介紹。然而目前,我們只會介紹與處理生命周期事件的兩個屬性。
名稱 | 描述 |
CurrentNotification | 這個屬性會使用 System.Web.RequestNotification 枚舉中的值來指示當前應用事件。 |
IsPostNotification | 如果 CurrentNotification 屬性返回的當前應用事件名稱是 Post<Name> 的變體,那麼這個屬性就會返回 true。 |
這兩個屬性有一點奇怪,因為兩者都需要計算出哪個事件正在被處理。CurrentNotification 屬性返回一個 RequestNotification 枚舉值,當中定義了 HttpApplication 事件的子集。IsPostNotification 屬性值是根據當前觸發的事件是否是一個像 AcquireRequestState 的事件還是與其配對的 PostAcquireRequestState 事件計算出來的。在 HttpApplication 類中,可以通過 Context 屬性獲取到 HttpContext 對象。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using System.Web.Routing; 7 8 namespace SimpleApp 9 { 10 public class MvcApplication : System.Web.HttpApplication 11 { 12 public MvcApplication() 13 { 14 BeginRequest += RecordEvent; 15 AuthenticateRequest += RecordEvent; 16 PostAuthenticateRequest += RecordEvent; 17 } 18 19 protected void Application_Start() 20 { 21 AreaRegistration.RegisterAllAreas(); 22 RouteConfig.RegisterRoutes(RouteTable.Routes); 23 } 24 25 private void RecordEvent(object src, EventArgs args) 26 { 27 List<string> eventList = Application["events"] as List<string>; 28 if (eventList == null) 29 { 30 Application["events"] = eventList = new List<string>(); 31 } 32 string name = Context.CurrentNotification.ToString(); 33 if (Context.IsPostNotification) 34 { 35 name = "Post" + name; 36 } 37 eventList.Add(name); 38 } 39 } 40 }View Code
我改變了 RecordEvent 方法的簽名,因此採用了標準的事件處理器簽名:一個對象代表的是事件的源,EventArgs 對象描述的就是事件。我沒有使用這兩個參數提供的值,相反,我使用了 Context.CurrentNotification 屬性和 Context.IsPostNotification 屬性提供的相關信息。
我不明白微軟為什麼以這樣的一個方式來實現事件,但是如果你不想使用特殊方法或者 lambda 表達式的話,那你就必須使用這種方式。註意到,在上面的代碼中,我在 Context.CurrentNotification 屬性上使用了 ToString 方法,這是必須的,因為 CurrentNotification 屬性返回的是一個 System.Web.RequestNotification 枚舉值。詳見下表:
表 1 – RequestNotification 枚舉值
值 | 描述 |
BeginRequest | 對應到 BeginRequest 事件 |
AuthenticateRequest | 對應到 AuthenticateRequest 和 PostAuthenticateRequest 事件 |
AuthorizeRequest | 對應到 AuthorizeRequest 事件 |
ResolveRequestCache | 對應到 ResolveRequestCache 和 PostResolveRequestCache 事件 |
MapRequestHandler | 對應到 MapRequestHandler和 PostMapRequestHandler 事件 |
AcquireRequestState | 對應到 AcquireRequestState 和 PostRequestState 事件 |
PreExecuteRequestHandler | 對應到 PreExecuteRequestHandler 事件 |
ExecuteRequestHandler | 對應到 ExecuteRequestHandler 事件 |
ReleaseRequestState | 對應到 ReleaseRequestState 和 PostReleaseRequestState 事件 |
UpdateRequestCache | 對應到 UpdateRequestCahce 事件 |
LogRequest | 對應到 LogRequest 事件 |
EndRequest | 對應到 EndRequest 事件 |
SendResponse | 指示響應正在被髮送——不完全對應到 PreSendRequestHeaders 和 PreSendRequestContent 事件 |
[根據 Adam Freeman – Pro ASP.NET MVC 5 Platform 選譯]