Pro ASP.NET MVC 5 Platform-第三章 ASP.NET 生命周期

一、 ASP.NET 生命周期:

ASP.NET MVC有两个生命周期:应用程序生命周期和请求生命周期。

1. 应用程序生命周期 (Applicatin Life Cycle)

从应用程序启动到应用程序结束的时间

理解应用程序生命周期:

What:应用程序生命周期通知允许在程序启动和关闭时,执行自己的代码

Why:利用应用程序生命周期通知,我们可以在启动程序时完成一些配置工作,关闭程序时,释放一些资源。通常在应用程序启动时,配置依赖注入容器。

How: 在MVC中,利用应用程序通知,我们配置路由,区域,全局过滤器,内容绑定等。

在MVC中有关应用程序生命周期的文件:Global.asax.cs

public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); } }

HttpApplication: 定义 ASP.NET 应用程序中的所有应用程序对象共有的方法、属性和事件。此类是用户在 Global.asax 文件中所定义的应用程序的基类。

利用应用程序生命周期,我们可以在程序启动和中止时,执行相应代码。

Application_Start :应用程序启动后,我们可以配置写全局的设置

Application_End: 应用程序结束前,我们可以释放一些资源,数据库链接

需要注意一点:

这两个方法没有在基类中定义,ASP.NET MVC方法通过反射找到这两个方法,要特别注意名称不要写错。

测试程序启动和中止时的通知:System.Diagnostics.Debugger.Break method

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(); } }

2. 请求生命周期(Request Life Cycle)

从mvc接受请求到发出响应的时间。

理解请求生命周期

What: 请求生命周期包括一系列事件的执行,也称为请求管道

Why: 利用请求管道里的事件,我们可以自定义Module和Handler.

How: MVC包含一些模块和处理 程序,模块拦截请求,选择Handler,handler负责具体选择Conroller和Action。

请求管道中的事件:

1、BeginRequest:HTTP管道开始处理请求时,会触发BeginRequest事件

2、AuthenticateRequest:安全模块对请求进行身份验证时触发该事件

3、PostAuthenticateRequest:安全模块对请求进行身份验证后触发该事件

4、AuthorizeRequest:安全模块对请求进程授权时触发该事件

5、PostAuthorizeRequest:安全模块对请求进程授权后触发该事件

6、ResolveRequestCache:缓存模块利用缓存直接对请求进程响应时触发该事件

7、PostResolveRequestCache:缓存模块利用缓存直接对请求进程响应后触发该事件

8、PostMapRequestHandler:对于访问不同的资源类型,ASP.NET具有不同的HttpHandler对其进程处理。对于每个请求,ASP.NET会根据扩展名选择匹配相应的HttpHandler类型,成功匹配后触发该事件

9、AcquireRequestState:状态管理模块获取基于当前请求相应的状态(比如SessionState)时触发该事件

10、PostAcquireRequestState:状态管理模块获取基于当前请求相应的状态(比如SessionState)后触发该事件

11、PreRequestHandlerExecute:在实行HttpHandler前触发该事件

12、PostRequestHandlerExecute:在实行HttpHandler后触发该事件

13、ReleaseRequestState:状态管理模块释放基于当前请求相应的状态时触发该事件

14、PostReleaseRequestState:状态管理模块释放基于当前请求相应的状态后触发该事件

15、UpdateRequestCache:缓存模块将HttpHandler处理请求得到的相应保存到输出缓存时触发该事件

16、PostUpdateRequestCache:缓存模块将HttpHandler处理请求得到的相应保存到输出缓存后触发该事件

17、LogRequest:为当前请求进程日志记录时触发该事件

18、PostLogReques:为当前请求进程日志记录后触发该事件

19、EndRequest:整个请求处理完成后触发该事件

注意:

ASP.NET 会创建多个MvcApplication实例来处理请求,这些实例可以复用,但是每个实例一次只能处理一个请求。

3. 理解Module和Handler

HttpModule

ASP.NET拥有一个高度可扩展的引擎,并且能够处理对于不同资源类型的请求。这就是HttpModule。当一个请求转入ASP.net管道时,最终负责处理请求的是与资源相匹配的HttpHandler对象,但是在HttpHandler进行处理之前,ASP.NET先会加载并初始化所有配置的HttpModule对象。

HttpModule初始化的时候,会将一些回调事件注入到HttpApplication相应的事件中。所有的HttpModule都实现了IHttpModule接口,该接口有一个有一个Init方法。

HttpHandler

对于不同的资源类型的请求,ASP.NET会加载不同的HttpHandler来处理。所有的HttpHandler都实现了IhttpHandler接口。

我们看到该接口有一个方法ProcessRequest,顾名思义这个方法就是主要用来处理请求的。所以说每一个请求最终分发到自己相应的HttpHandler来处理该请求。

HttpHandle和HttpModule的区别:

HttpHandler是每个请求的主要处理对象,而HttpModule可以选择请求交给哪个HttpHandler来处理, 甚至,它还可以选择它自己来处理请求。

可以把Module想象成老板,既接活,有时还自己干活,Handler是员工,只负责干活。

1)用方法记录请求生命周期中的事件:

这种方法只能记录:PreRequestHanderExecute之后PostRequestHandlerExecute之前的事件

protected void Application_BeginRequest() { RecordEvent("BeginRequest"); } private void RecordEvent(string name) { List<string> eventList = Application["events"] as List<string>; if (eventList == null) { Application["events"] = eventList = new List<string>(); } eventList.Add(name); }

显示事件信息:

return View(HttpContext.Application["events"]);

2)利用HttpApplication类的事件,记录事件信息

BeginRequest += (src, args) => RecordEvent("BeginRequest"); public MvcApplication() { BeginRequest += (src, args) => RecordEvent("BeginRequest"); AuthenticateRequest += (src, args) => RecordEvent("AuthentucateRequest"); PostAuthenticateRequest += (src, args) => RecordEvent("PostAuthenticateRequest"); } private void RecordEvent(string name) { List<string> eventList = Application["events"] as List<string>; if (eventList == null) { Application["events"] = eventList = new List<string>(); } eventList.Add(name); }

3)使用一个方法记录多个事件

SystemWeb.HttpContext类的两个属性:CurrentNotification, IsPostNotification

public MvcApplication() { BeginRequest += RecordEvent; AuthenticateRequest += RecordEvent; PostAuthenticateRequest += RecordEvent; } private void RecordEvent(object src, EventArgs args) { List<string> eventList = Application["events"] as List<string>; if (eventList == null) { Application["events"] = eventList = new List<string>(); } string name = Context.CurrentNotification.ToString(); if (Context.IsPostNotification) { name = "Post" + name; } eventList.Add(name); }

Context.CurrentNotification返回为一个RequestNotification枚举值,描述当前执行的事件。

MVC中关于RequestNotification枚举值的定义:

4. ASP.NET 上下文对象:

HttpContext基于HttpApplication的处理管道,由于HttpContext对象贯穿整个处理过程,所以,可以从HttpApplication处理管道的前端将状态数据传递到管道的后端,完成状态的传递任务。

HttpContext的生命周期从服务器接收的HTTP请求开始到反应发送回客户端结束。

HttpContext成员:

属性:

Application 为当前 HTTP 请求获取 HttpApplicationState 对象。

ApplicationInstance 返回与当前请求相关的HttpApplication对象

Cache 获取当前应用程序域的 Cache 对象。

Current 为当前 HTTP 请求获取或设置 HttpContext 对象。

CurrentHandler 获取表示当前正在执行的处理程序的 IHttpHandler 对象。

IsDebuggingEnabled 显示当前应用程序是否处于调试状态

Items 获取可用于在 HTTP 请求过程中在 IHttpModule 接口和 IHttpHandler 接口之间组织和共享数据的键/值集合。

GetSection(name) 获取当前应用程序的默认配置的指定配置节。

Request 为当前 HTTP 请求获取 HttpRequest 对象。

Response 为当前 HTTP 响应获取 HttpResponse 对象。

Session 为当前 HTTP 请求获取 HttpSessionState 对象。

Server 获取提供用于处理 Web 请求的方法的 HttpServerUtility 对象。

Timestamp 获取当前 HttpContext创建时的时间点,类型为:DateTime

Trace 用于记录诊断信息

CurrentNotification 获取请求管道中当前执行的事件,返回RequestNotification枚举

IsPostNotification 是否Post类事件

方法:

AddError 将异常添加到当前 HTTP 请求的异常集合中。

ClearError 清除当前 HTTP 请求的所有错误

GetGlobalResourceObject 获取应用程序级别的资源。

GetLocalResourceObjec   获取页级别的资源。

GetSection 获取当前应用程序的默认配置的指定配置节。

RemapHandler 用于为请求指定处理程序。

RewritePath 重写路径,以便后续的Asp.net以为这是才是真正的地址。RewritePath用在无 Cookie 会话状态中。

在ASP.NET MVC不同的组件获取HttpContext:

Controller: 使用Controller定义的HttpContext

View: 使用WebViewPage定义的Context属性

Global.asax: 使用HttpApplication类定义的Context

Module: HttpContext.Current

Handler: ProcessRequest方法参数HttpContext

通用: HttpContext.Current

理解HttpContext,HttpContextBase,HttpContextWrapper的区别和联系:

HttpContext

HttpContext是最原始的ASP.NET Context. MVC的目的之一是能够单元测试。HttpContext没有base class,并且不是virtual,所以不能用单元测试,因为没有办法mock.

HttpContextBase

HttpContextBase, 是用来在MVC中替代HttpContext.但是这是一个abstract类,是mockable的。

HttpContextWrapper

HttpContextWrapper 是HttpContextBase的实现类,用来真正的替换HttpContext,可以用new HttpContextWrapper(HttpContext.Current)的方式来创建一个ttpContextWrapper.观察代码可以发 现,HttpContext与HttpContextWrapper在属性方法设置上基本上是一样的,只是HttpContextWrapper不是 virtual,有base class,因此可以进行单元测试。现在,关于使用到HttpContext的方法,可以通过HttpContextWrapper来进行单元测试。观察 ASP.NET MVC的源码可以发现,在最终MVCHandler(ASP.NET MVC的HttpHandler)中,调用ProcessRequest(HttpContext context)方法的时候,其内部把HttpContext转为HttpContextWrapper,然后调用了 ProcessRequest(HttpContext context)来进行后续的处理。

5. HttpApplication

HttpApplication:常用成员:

Application 与HttpContext.Application属性对应,获取应用程序级别的状态数据

CompleteRequest() 中止当前请求生命周期,直接跳转到LogRequest事件

Context 获取当前请求的HttpContext对象

Init() 当每个注册模块的Inti()方法执行时,执行Init()方法

Modules 返回HttpModuleCollection对象,包括应用程序的所有模块细节

RegisterModule(type) 注册新模块的静态方法

Request 返回HttpContext.Request,如果为空,则引发HttpException异常

Response 返回HttpContext.Response,如果为空,则引发HttpException异常

Server 与HttpContext.Server属性相同

Session 返回HttpContext.Session,如果为空,则引发HttpException异常

处理属性异常(HttpApplication的使用):

如果在应用程序级别的通知事件中,访问与请求上下文相关的属性,就会引发异常:HttpExecption.

private void CreateTimeStamp() { string stamp = Context.Timestamp.ToLongTimeString(); if (Session != null) { //Session是请求上下文对象,在Global.asax类会引发异常 Session["request_timestamp"] = stamp; } else { Application["app_timestamp"] = stamp; } } 应该改为: private void CreateTimeStamp() { string stamp = Context.Timestamp.ToLongTimeString(); if (Context.Session != null) { Session["request_timestamp"] = stamp; } else { Application["app_timestamp"] = stamp; } }

注意,在一次请求中,方法执行了两次,这是因为ASP.NET生命周期中全局Application类处理所有请求,不只是MVC框架的。

6. HttpRequest

描述当前正在处理的请求,提供当前请求的信息。

HttpRequest类成员

AcceptTypes 获取客户端支持的 MIME 接受类型的字符串数组。

Browser 获取或设置有关正在请求的客户端的浏览器功能的信息。

ContentEncoding 获取或设置实体主体的字符集

ContentLength 客户端发送的内容长度(以字节计)。

ContentType 获取或设置传入请求的 MIME 内容类型。

CurrentExecutionFilePathExtension 获取当前请求的虚拟路径。

Headers 获取 HTTP 头集合。

HttpMethod 获取客户端使用的 HTTP 数据传输方法(如 GET、POST 或 HEAD)

InputStream 获取传入的HTTP 实体主体的内容

IsLocal 获取一个值,该值指示该请求是否来自本地计算机。

MapPath(path) 将指定的虚拟路径映射到物理路径。

RawUrl 获取当前请求的原始 URL

RequestContext 返回RequestContext对象,提供了当前请求的路由信息

Url 获取当前请求的原始 URL

UrlReferrer 获取有关客户端上次请求的 URL 的信息,该请求链接到当前的 URL

UserAgent 获取客户端浏览器的原始用户代理信息

UserHostAddress 获取远程客户端的 IP 主机地址

UserHostName 获取远程客户端的 DNS 名称

UserLanguages 取客户端语言首选项的排序字符串数组

Files 获取采用多部分 MIME 格式的由客户端上载的文件的集合。

Form 获取表单变量集合

Params 获取QueryString、Form、ServerVariables 和 Cookies 项的组合集合

QueryString 获取 HTTP 查询字符串变量集合

Item Item 从 Cookies、Form、QueryString 或 ServerVariables 集合中获取指定的对象

ApplicationPath 获取服务器上 ASP.NET 应用程序的虚拟应用程序根路径

Filter 获取或设置在读取当前输入流时要使用的筛选器

在MVC的View中使用Request对象:

<div class="panel panel-primary"> <h5 class="panel-heading">Request Properties</h5> <table class="table table-condensed table-striped"> <tr><th>Property</th><th>Value</th></tr> <tr><td>HttpMethod</td><td>@Request.HttpMethod</td></tr> <tr><td>IsLocal</td><td>@Request.IsLocal</td></tr> <tr><td>RawURL</td><td>@Request.RawUrl</td></tr> </table> </div>

在ASP.NET MVC的不同组件中获取HttpRequest对象

Controller Request

View Request

Global.asax Request

Module context.Request,context为Init方法传入的参数类型为HttpApplication

Handler context.Request,context为ProcessRequest方法的参数,类型为HttpContext

通用: HttpContext.Current.Request

7. HttpResponse

HttpResponse标识当前请求的响应,提供方法和属性,利用它们,可以自定义响应内容。

HttpResponse类成员:

AppendHeader(name,val) 将 HTTP 头添加到输出流

BufferOutput 获取或设置值,该值标识请求是否被缓冲输出

Cache 获取网页的缓存策略(过期时间、保密性、变化子句)

CacheControl 获取或设置输出的cache-control头部信息

ContentType 获取或设置输出流的 HTTP MIME 类型。默认值为“text/html”

Cookies 获取响应 Cookie 集合

Filter 获取或设置一个包装筛选器对象,该对象用于在传输之前修改 HTTP 实体主体

Charset 获取或设置HTTP的输出字符串编码

Clear() 将缓冲区中的内容清除

ClearContent() 与Clear方法相同

ClearHeader() 移除响应流中的头部信息

ContentEncoding 获取或设置响应内容的编码

Headers 获取Response的头部信息集合

IsClientConnected 客户端是否与服务端连接

Output 返回TextWriter,用于将文本信息输出到Response

OutputStream 启用到输出 Http 内容主体的二进制输出

Redirect 将客户端重定向到新的 URL。指定新的 URL 并指定当前页的执行是否应终止。

Status

StatusCode 获取或设置返回给客户端的输出的 HTTP 状态代码。默认值为 200 (OK)。

SuppressContent 设置是否将HTTP内容发送到客户端浏览器,若为true,网页将不会传送给客户端

Write(data) 将数据写入HTTP响应流

WriteFile(path) 将指定的文件直接写入HTTP内容输出流

End 将当前所有缓冲的输出发送到客户端,停止该页的执行,并引发EndRequest事件。

TransmitFile 将指定的文件直接写入 HTTP 响应输出流,而不在内存中缓冲该文件

ASP.NET MVC不同的组件获取HttpResponse的方法:

Controller Response

View Response

Global.asax Response

Module context.Response,context为Init方法传入的HttpApplication类参数

Handler context.Response,ProcessRequest方法的参数,类型为HttpContext

通用: HttpContext.Current.Response

参考:

IIS5 IIS6

https://docs.microsoft.com/zh-cn/previous-versions/aspnet/ms178473%28v%3dvs.100%29

IIS7

https://docs.microsoft.com/en-us/previous-versions/aspnet/bb470252(v=vs.100)

ASP.NET 应用程序生命周期和请求周期

https://www.cnblogs.com/alunchen/p/6252846.html

WCF技术剖析之二:再谈IIS与ASP.NET管道

http://www.cnblogs.com/artech/archive/2009/06/20/1507165.html

Asp.net的生命周期应用之IHttpModule和IHttpHandler

https://www.cnblogs.com/anlen/p/3613186.html

ASP.NET-自定义HttpModule与HttpHandler

https://www.cnblogs.com/fengzheng/p/3666774.html

ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19)

http://www.cnblogs.com/darrenji/p/3795690.html

ASP.NET 应用程序生命周期概述[转自MSDN]

https://www.cnblogs.com/stg609/articles/1224943.html

asp.net MVC 应用程序的生命周期

http://www.cnblogs.com/yplong/p/5582576.html

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

https://www.cnblogs.com/anlen/p/3612048.html

ASP.NET是如何在IIS下工作的

https://www.cnblogs.com/fengzheng/p/3668283.html

我心目中的Asp.net核心对象

https://www.cnblogs.com/fish-li/archive/2011/08/21/2148640.html

ASP.NET MVC5请求管道和生命周期

https://www.jianshu.com/p/848fda7f79e0

ASP.NET MVC中HttpContext, HttpContextBase, HttpContextWrapper联系

https://www.cnblogs.com/BluceLee/p/3679052.html

HttpContext请求上下文对象

https://www.cnblogs.com/kissdodog/p/3360584.html

IIS 7.0的集成模式和经典模式

http://www.cnblogs.com/elock/archive/2009/12/26/1632838.html

HttpRequest成员

http://www.php230.com/1415360402.html

原文地址:https://www.cnblogs.com/AlexanderZhao/p/12878929.html