[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)

不使用特殊方法来处理请求生命周期事件

HttpApplication 类是全局应用类的基类,定义了可以直接使用的一般 C# 事件。那么使用标准 C# 事件还是特殊方法那就是个人偏好的问题了,如果喜欢,也可以将这两种方式混合起来使用。

[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)
 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 对象。

[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)
 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 选译]

上一篇:Winform开发框架的业务对象统一调用方式


下一篇:MVC架构探究及其源码实现(4)-前端控制器