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

时间:2022-08-13 19:21:47

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

为了在全局应用类中处理这些事件,我们会创建一个名称以 Application_ 开头,以事件名称结尾的方法,比如 Application_BeginRequest。举个例子,就像 Application_Start 和 Application_End 方法,ASP.NET 框架就会在事件触发的时候找到这些函数并触发它。下面是更新后的代码片段:

[译] 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 protected void Application_Start()
13 {
14 AreaRegistration.RegisterAllAreas();
15 RouteConfig.RegisterRoutes(RouteTable.Routes);
16 }
17
18 protected void Application_BeginRequest()
19 {
20 RecordEvent("BeginRequest");
21 }
22
23 protected void Application_AuthenticateRequest()
24 {
25 RecordEvent("AuthenticateRequest");
26 }
27
28 protected void Application_PostAuthenticateRequest()
29 {
30 RecordEvent("PostAuthenticateRequest");
31 }
32
33 private void RecordEvent(string name)
34 {
35 List<string> eventList = Application["events"] as List<string>;
36 if (eventList == null)
37 {
38 Application["events"] = eventList = new List<string>();
39 }
40 eventList.Add(name);
41 }
42 }
43 }
View Code

我定义了一个叫做 RecordEvent 的方法,用来接收一个事件的名称作为参数,并将其存储到 HttpApplication 类的 Application 属性中。

注意:在没有深入了解 Application 属性之前,请勿滥用这个属性。

我从添加到全局应用类中的其他三个方法中调用了 RecordEvent 方法。这些方法会在 BeginRequest, AuthenticateRequest 和 PostAuthenticateRequest 触发的时候被调用。我们暂时不需要将这些函数显式注册成事件处理器,ASP.NET 框架会自动定位和调用这些函数。

展示事件信息

为了展示我们代码中接收到的事件的信息,我们需要更改 Home controller 和它的 Index 视图。代码如下:

[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(三)[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(三)
 1 using SimpleApp.Models;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Mvc;
7
8 namespace SimpleApp.Controllers
9 {
10 public class HomeController : Controller
11 {
12 public ActionResult Index()
13 {
14 return View(HttpContext.Application["events"]);
15 }
16
17 [HttpPost]
18 public ActionResult Index(Color color)
19 {
20 Color? oldColor = Session["color"] as Color?;
21
22 if (oldColor != null)
23 {
24 Votes.ChangeVote(color, (Color)oldColor);
25 }
26 else
27 {
28 Votes.RecordVote(color);
29 }
30
31 ViewBag.SelectedColor = Session["color"] = color;
32 return View(HttpContext.Application["events"]);
33 }
34 }
35 }
View Code

为了获取到存储在全局应用类中的数据,我们需要使用到 HttpContext.Application 属性,我们后面会详细讲解上下文对象。现在,我们需要更新相关的 Razor 视图:

[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(三)[译] ASP.NET 生命周期 – ASP.NET 请求生命周期(三)
 1 @using SimpleApp.Models
2 @model List<string>
3 @{
4 Layout = null;
5 }
6
7 <!DOCTYPE html>
8
9 <html>
10 <head>
11 <meta charset="utf-8" />
12 <meta name="viewport" content="width=device-width" />
13 <title>Vote</title>
14 <link rel="stylesheet" href="~/Content/bootstrap.min.css" />
15 <link rel="stylesheet" href="~/Content/bootstrap-theme.min.css" />
16 </head>
17 <body class="container">
18 <div class="panel panel-primary">
19
20 @if (ViewBag.SelectedColor == null)
21 {
22 <h4 class="panel-heading">Vote for your favourite color</h4>
23 }
24 else
25 {
26 <h4 class="panel-heading">Change your vote from @ViewBag.SelectedColor</h4>
27 }
28
29 <div class="panel-body">
30 @using (Html.BeginForm())
31 {
32 @Html.DropDownList("color", new SelectList(Enum.GetValues(typeof(Color))), "Choose a Color", new { @class = "form-control" })
33
34 <div>
35 <button class="btn btn-primary center-block" type="submit">Vote</button>
36 </div>
37 }
38 </div>
39 </div>
40
41 <div class="panel panel-primary">
42 <h5 class="panel-heading">Results</h5>
43
44 <table class="table table-striped table-condensed">
45 <tr>
46 <th>Color</th>
47 <th>Votes</th>
48 </tr>
49 @foreach (Color c in Enum.GetValues(typeof(Color)))
50 {
51 <tr>
52 <td>@c</td>
53 <td>@Votes.GetVotes(c)</td>
54 </tr>
55 }
56 </table>
57 </div>
58
59 <div class="panel panel-primary">
60 <h5 class="panel-heading">Events</h5>
61 <table class="table table-condensed table-striped">
62 @foreach (string eventName in Model)
63 {
64 <tr><td>@eventName</td></tr>
65 }
66 </table>
67 </div>
68 </body>
69 </html>
View Code

事件名称列表作为模型对象传递到视图中,我们使用 Razor foreach 循环来生成 HTML table 元素。

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

图 1 - 展示生命周期事件详情

提示:这种技术只能使用在排在 PreRequestHandlerExecute 事件之前的事件之上,因为 controller 中的 action 方法会在 PreRequestHandlerExecute 和 PostRequestHandlerExecute 事件之间执行,所以后续触发的事件都已经在响应生成好之后发生了。

[根据 Adam Freeman – Pro ASP.NET MVC 5 Platform 选译]