概述

ASP.NET 平台定义了两个非常重要的生命周期。第一个是 应用生命周期  (application life cycle),用来追踪应用从启动的那一刻到终止的那一刻。另一个就是 请求生命周期 (request life cycle),它定义了 HTTP 请求在 ASP.NET 平台中首次接收到,到最终响应发出之间的路径。

ASP.NET 应用生命周期

在 ASP.NET 中有两个时刻——应用启动的时刻和应用停止接收请求的时刻,这两个时刻定义了应用生命周期。ASP.NET 在应用启动和当应用在可控的情况下停止的时候提供了通知功能,我们接下来就讨论这样的通知功能。

应用生命周期通知允许了我们在应用启动或者应用在可控的情况下停止的时候执行某些任务。如果我们在应用启动的时候需要执行一次性的配置任务或者在应用停止的时候需要释放资源的时候,通知就会变得非常有用。MVC 框架开发者在应用生命周期中最常使用的就是配置一个依赖注入容器。MVC 框架使用应用生命周期来执行与请求相关的配置任务,比如建立 routes, areas, 和 content bundles。

理解应用生命周期

ASP.NET 应用的生命周期从应用启动的那一刻开始,在接收 HTTP 请求并处理生成响应的过程中一直延续。这包括将请求分配到合适的 controllers, actions 上,并从 Razor 视图中渲染内容。生命周期直到应用停止的那一刻结束。

全局应用类在早期版本的 ASP.NET 中就已经存在了,它包含有两个文件:Global.asax 和 Global.asax.cs。严格来讲,Global.asax 文件才是全局应用类,而 Global.asax.cs 文件是与之关联的隐藏代码 (code-behind) 文件。这是一个很经典的 Web Forms 将声明性代码与编程性代码分开的做法,但是现在,这仅仅是为了兼容性,即使在 Web Forms 项目中。下面是 Global.asax 文件中的内容,在 MVC 框架项目中,我们从不需要修改这个文件。

 <%@ Application Codebehind="Global.asax.cs" Inherits="SimpleApp.MvcApplication" Language="C#" %>

之前版本中遗留下来的 Global.asax 文件多少都会有点有趣,但是,我们关注的重点还是 Global.asax.cs 文件。这个文件的角色在 ASP.NET 进化的过程中也慢慢地改变了,现在 全局应用类 这个术语一般直接用来指 Global.asax.cs 文件了,在解决方案资源管理器中双击 Global.asax 文件直接打开 Global.asax.cs 文件你就可以明白其中缘由了。

下面是案例项目中 Global.asax.cs 文件中的内容:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace SimpleApp
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
}

默认的全局应用类叫做 MvcApplication,继承自 System.Web.HttpApplication 类。我们在后面会接触到更多的 System.Web 命名空间下面的类。

MvcApplication 类由 ASP.NET 框架实例化,这里面定义的方法会在应用生命周期的关键时刻被调用。

默认的 MvcApplication 类中只包含了一个方法,叫做 Application_Start,但是还有另外一个方法可用,接下来我们就来介绍。

应用启动和停止的时候接收通知

全局应用类支持两种特殊的方法用来定义应用生命周期的开始与结束:

名称 描述
Application_Start() 当应用启动的时候调用
Application_End() 当应用将要终止的时候调用

Application_Start 方法在应用第一次启动的时候被调用,并且提供了执行一次性配置任务的机会。比如,Visual Studio 在 Application_Start 方法中添加了建立 MVC areas 和 URL routes 的声明。

Application_End方法仅会在应用终结之前执行,提供了释放资源的机会。通常使用这个方法的理由就是释放数据库的连接,但是大多数的现代应用都不直接管理这样的连接,我很少在自己的项目中使用到这个方法。而如今,数据库已经能够足够好的管理它们的连接,而且,Application_End 方法仅会在应用在一个可控制的方式下关闭才会被调用到。因此我们不能够依赖这个方法,因为服务器可能发生不可预知的故障,比如突然断电,这就会导致 Application_End 方法并不会被执行。

我说这些方法是 特殊 的是因为它们实现的方式特别。这些方法并没有定义在全局应用类的基类中 (System.Web.HttpApplication),所以我们并不需要使用 override 关键字来实现它们。事实上,ASP.NET 框架使用反射的方式根据方法名称来检索它们。如果你写错了方法的名称并不会得到任何的错误提示,ASP.NET 会假设你在应用开始或者结束的时候不想得到通知。正因为这样,测试并确保你的代码能够被执行是非常重要的。

提示:有时候,我们在 Application_Start 和 Application_End 方法的定义中看到 Object 和 EventArgs 参数,这是为了遵循 C# 事件处理器方法的约定。这是可选的,ASP.NET 框架能够定位到那些有这两个参数或者没有参数的方法。

图 1 - 应用生命周期

测试启动和停止通知

我们可以在应用中直接使用 Application_Start 和 Application_End 方法来执行一次性的启动和关闭任务。接下来,我将会教大家怎么使用调试器来确保者两个方法能够被执行——特别是在我们自定义代码不能够像我们预期的那样执行的时候显得格外重要。

最简单的方法来测试这些方法是否被执行就是使用 Visual Studio 的调试器,下面的代码片段中,我们会看到怎么在 Application_start 和 Application_End 方法中调用添加的静态 System.Diagnostics.Debugger.Break 方法,这和我们在 Visual Studio 代码编辑器中直接设置一个断点的效果是一样的。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace SimpleApp
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
System.Diagnostics.Debugger.Break();
} protected void Application_End()
{
System.Diagnostics.Debugger.Break();
}
}
}

测试启动通知

测试 Application_Start 方法是非常简单的,在 Visual Studio 调试菜单中选择启动调试,Visual Studio 会打开一个浏览器窗口。ASP.NET 框架开始初始化这个应用,创建了一个全局应用类的实例,发现了 Application_Start 方法,然后调用它,这将会引起 Break 方法被调用。应用的执行将会暂停,控制将会传递给调试器,如下图所示:

图 2 - Application_Start 方法调用的时候控制传递给调试器

在调试菜单中选择继续,应用的执行将会恢复。来自浏览器的请求将会被处理,并生成相应的 HTML 响应发送给用户。

测试停止通知

测试 Application_End 方法有一点点困难,因为如果选择停止调试将会导致在 Application_End 方法被调用之前调试器将会从应用上分离出去。浏览器窗口关闭,调试器终止掉,Visual Studio 将会返回到默认的状态——然而,Debugger.Break 方法并没有被调用。

为了测试 Application_End 中的代码,我们必须直接使用 IIS Express,而非通过 Visual Studio。IIS Express 是 Visual Studio 中自带的一个简化版的 IIS 应用服务器,只是用于在开发过程中运行 ASP.NET 应用的。

在 Windows 任务栏中定位到 IIS Express 图标,右击它会有一个弹窗菜单出现。在菜单项目中,我们会看到一个 SimpleApp 项目(应用名称),当你选中它的时候会看到一个停止站点菜单项目,如下图所示:

图 3 - 使用 IIS Express 停止一个应用

当选择停止站点的时候,IIS Express 会停止这个应用,作为处理过程的一部分,Application_End方法将会被调用。在本例中,Debugger.Break 方法将会被调用,如下图所示:

图 4 - 测试 Application_End 方法中的代码

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

[译] ASP.NET 生命周期 – ASP.NET 应用生命周期(一)的更多相关文章

  1. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(五)

    ASP.NET 上下文对象 ASP.NET 提供了一系列对象用来给当前请求,将要返回到客户端的响应,以及 Web 应用本身提供上下文信息.间接的,这些上下文对象也可以用来回去核心 ASP.NET 框架 ...

  2. .net学习笔记---Asp.net的生命周期之二页生命周期

    用户请求 从 用户角度来说,我不管你后台经历了什么,我只想要我请求的页面.请求到服务器端,服务器必须得有所表示的是吧,即使不想搭理人家也得让IIS给人家说声:找不到服务器.请求来到服务器端,肯定要让服 ...

  3. ASP.NET Web 应用程序及页面生命周期

    以客户端浏览器向 ASP.NET Web 应用程序页面发送请求(Request)为起点,以浏览器收到 Web 服务器的响应(Response)为终点,这一完整的过程被称为"应用程序及页面的生 ...

  4. 【深入ASP.NET原理系列】--ASP.NET请求管道、应用程序生命周期、整体运行机制

    微软的程序设计和相应的IDE做的很棒,让人很快就能有生产力..NET上手容易,生产力很高,但对于一个不是那么勤奋的人,他很可能就不再进步了,没有想深入下去的动力,他不用去理解整个框架和环境是怎么执行的 ...

  5. atitit.提升开发效率---使用服务器控件生命周期 asp.net 11个阶段 java jsf 的6个阶段比较

    atitit.提升开发效率---使用服务器控件生命周期  asp.net 11个阶段  java jsf 的6个阶段比较 如下列举了服务器控件生命周期所要经历的11个阶段. (1)初始化-- --在此 ...

  6. .net学习笔记----Asp.net的生命周期之一应用程序生命周期

    Http请求刚刚到达服务器的时候 当服务器接收到一个 Http请求的时候,IIS (Internet Information Services,互联网信息服务)首先需要决定如何去处理这个请求. 什么是 ...

  7. Asp.net的生命周期之应用程序生命周期

    参考:http://msdn.microsoft.com/zh-cn/library/ms178473(v=vs.100).aspx 参考:http://www.cnblogs.com/JimmyZh ...

  8. atitit.提升开发效率---使用server控件生命周期 asp.net 11个阶段 java jsf 的6个阶段比較

    atitit.提升开发效率---使用server控件生命周期  asp.net 11个阶段  java jsf 的6个阶段比較 例如以下列举了server控件生命周期所要经历的11个阶段. (1)初始 ...

  9. ASP.NET请求管道、应用程序生命周期、整体运行机制

    我们知道在ASP.NET中,若要对ASP.NET应用程序进行 初始化并使它处理请求,必须执行一些处理步骤,熟悉应用程序生命周期非常重要,这样才能在适当的生命周期阶段编写代码,达到预期的效果.永远不要做 ...

随机推荐

  1. 用继承实现XYPoint和Circle两个类

    #import <Foundation/Foundation.h> @protocol show @required -(void)printOn; @end @interface XYP ...

  2. Android 自学之对话框

    Android为我们提供了丰富的对话框支持,提供了四种常用的对话框: AlertDialog:功能丰富.实际应用最广泛的对话框. ProgressDialog:进度对话框,该对话框只用于简单的进度条封 ...

  3. [转]Response.AddHeader 文本下载

    本文转自:http://hi.baidu.com/yuxi981/item/7c617fc41b03ad60f6c95d30 Response.AddHeader实现下载     /// <su ...

  4. [BigData]关于Hadoop学习笔记第三天(PPT总结)(一)

     课程安排 MapReduce原理*** MapReduce执行过程** 数据类型与格式*** Writable接口与序列化机制*** ---------------------------加深拓展- ...

  5. hdu 4665 搜索

    思路:直接搜索 #include<iostream> #include<cstdio> #include<algorithm> #include<cstrin ...

  6. Android中更新视图的函数onDraw()和dispatchdraw()函数的区别

    Android的view组件显示主要经过mesure, layout和draw这三个过程.在mesure阶段里调用mesure(int widthSpec, int heightSpec)方法,这个方 ...

  7. Android 中的 Service 全面总结 (转)

    原文地址:http://www.cnblogs.com/newcj/archive/2011/05/30/2061370.html 1.Service的种类   按运行地点分类: 类别 区别  优点 ...

  8. php中preg_match用户名正则实例

    例子,字母.数字和汉字  代码如下 复制代码 if(preg_match("/[ '.,:;*?~`!@#$%^&+=)(<>{}]|]|[|/|\|"||/& ...

  9. 【转载】 c语言inline函数的使用

    c语言inline函数的使用 转载自:http://blog.chinaunix.net/uid-21843265-id-3056446.html 大学在教科书上学习过inline函数,定义为inli ...

  10. 第九篇、Swift的基本使用

    1.访问权限 /* 1> internal : 内部的 1. 默认情况下所有的类&属性&方法的访问权限都是internal 2. 在本模块(项目/包/target)中可以访问 2 ...