Asp.net mvc应用程序生命周期
一、iis生命周期
1. 用户输入www.53bk.com
2. 到达服务器iis,IIS的HTTP.SYS 的内置驱动程序来监听来自外部的 HTTP请求。I
3. iis服务器的HTTP.SYS交给ISAPI,ISAPI处理网址扩展名,ISAPI提交给了aspnet_isapi.dll以后,接着就是只是等待结果。
4. aspnet_isapi.dll提交给asp.net mvc应用程序处理(转到应用程序生命周期)。
5. 应用程序返回结果给iis,iis再返回给用户(实际是IIS 接收返回的数据流,并重新返还给 HTTP.SYS,HTTP.SYS 再将这些数据返回给客户端浏览器)。
二、应用程序生命周期(这个是iis生命周期的一部分)
Asp.Net Mvc只是服务器(IIS)的一个组成部分而已,它是一个 ISAPI扩展
如果文件扩展名尚未映射到 ASP.NET,则 ASP.NET 将不会接收该请求。例如,由于 .htm 文件通常没有映射到 ASP.NET,因此 ASP.NET 将不会对 .htm 文件请求执行身份验证或授权检查。
1.BeginRequest 在 ASP.NET 响应请求时作为 HTTP 执行管线链中的第一个事件发生
2.AuthenticateRequest 当安全模块已建立用户标识时发生。注:AuthenticateRequest事件发出信号表示配置的身份验证机制已对当前请求进行了身份验证。预订 AuthenticateRequest 事件可确保在处理附加的模块或事件处理程序之前对请求进行身份验证
3.PostAuthenticateRequest 当安全模块已建立用户标识时发生
4.AuthorizeRequest 当安全模块已验证用户授权时发生。
5.PostAuthorizeRequest 在当前请求的用户已获授权时发生。
6.ResolveRequestCache 当 ASP.NET 完成授权事件以使缓存模块从缓存中为请求提供服务时发生,从而跳过事件处理程序(例如某个页或 XML Web services)的执行。这个事件还可以用来判断正文是不是从Cache中得到的。
7.PostResolveRequestCache 在 ASP.NET 跳过当前事件处理程序的执行并允许缓存模块满足来自缓存的请求时发生。
(asp.net mvc开始第一步工作)
8.PostMapRequestHandler 在 ASP.NET 已将当前请求映射到相应的事件处理程序时发生。 (asp.net mvc开始第二步工作)
9.AcquireRequestState 当 ASP.NET 获取与当前请求关联的当前状态(如会话状态)时发生。 (开始有Session)这里缓存页多用户只触发一次
10.PostAcquireRequestState 在已获得与当前请求关联的请求状态(例如会话状态)时发生。
11. PreRequestHandlerExecute 恰好在 ASP.NET 开始执行事件处理程序(例如,某页或某个 XML Web services)前发生。
12. ReleaseRequestState 在 ASP.NET 执行完所有请求事件处理程序后发生。该事件将使状态模块保存当前状态数据。
13. PostReleaseRequestState 在 ASP.NET 已完成所有请求事件处理程序的执行并且请求状态数据已存储时发生。
14. UpdateRequestCache 当 ASP.NET 执行完事件处理程序以使缓存模块存储将用于从缓存为后续请求提供服务的响应时发生。
15. PostUpdateRequestCache 在 ASP.NET 完成缓存模块的更新并存储了用于从缓存中为后续请求提供服务的响应后,发生此事件。
16. LogRequest 在 ASP.NET 完成缓存模块的更新并存储了用于从缓存中为后续请求提供服务的响应后,发生此事件。
(仅在 IIS 7.0 处于集成模式并且 .NET Framework 至少为 3.0 版本的情况下才支持此事件)
17. PostLogRequest 在 ASP.NET 处理完 LogRequest 事件的所有事件处理程序后发生。
(仅在 IIS 7.0 处于集成模式并且 .NET Framework 至少为 3.0 版本的情况下才支持此事件。)
18. EndRequest 在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生。
在调用 CompleteRequest 方法时始终引发 EndRequest 事件。
备注:
我们可以在Global.aspx文件中对HttpApplication的请求进行定制即注入这19个事件中的某个事件进行逻辑处理操作。在Global.aspx中我们按照"Application_{Event Name}"这样的方法命名进行事件注册。
Event Name就是上面19个事件的名称。比如Application_EndRequest就用于处理Application的EndRequest事件。
HttpModule
当一个请求转入ASP.net管道时,最终负责处理请求的是与资源相匹配的HttpHandler对象,但是在HttpHandler进行处理之前,ASP.NET先会加载并初始化所有配置的HttpModule对象。HttpModule初始化的时候,会将一些回调事件注入到HttpApplication相应的事件中。所有的HttpModule都实现了IHttpModule接口,该接口有一个有一个Init方法。
public interface IHttpModule
{
// Methods
void Dispose();
void Init(HttpApplication context);
}
看到Init方法呢接受一个HttpApplication对象,有了这个对象就很容易注册HttpApplication中19个事件中的某个事件了。这样当HttpApplication对象执行到某个事件的时候自然就会出发。
HttpHandler
对于不同的资源类型的请求,ASP.NET会加载不同的HttpHandler来处理。所有的HttpHandler都实现了IhttpHandler接口。
public interface IHttpHandler
{
// Methods
void ProcessRequest(HttpContext context);
// Properties
bool IsReusable { get; }
}
我们看到该接口有一个方法ProcessRequest,顾名思义这个方法就是主要用来处理请求的。所以说每一个请求最终分发到自己相应的HttpHandler来处理该请求。
ASP.NET MVC 运行机制
asp.net mvc是在什么时机获得了控制权并对请求进行处理呢?
既然asp.net mvc还是以asp.net运行时为基础那么它必然要在asp.net应用程序的生命周期中对请求进行截获。第一反应当然是去web.config里面去翻翻,我们可以看到UrlRoutingModule的配置节:
< add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
用Reflector打开这个程序集,可以看到以下代码:
protected virtual void Init(HttpApplication application)
{
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
}
看到这里我们的第一个问题实际上已经有了答案:时机是在PostResolveRequestCache和PostMapRequestHandler.
PostResolveRequestCache 开始的!!!!
到UrlRoutingModule实现了接口IHttpModule,当一个请求转入ASP.NET管道时,就会加载 UrlRoutingModule对象的Init()方法。
通过在全局Web.Config中注册 System.Web.Routing.UrlRoutingModule,IIS请求处理管道接到请求后,就会加载 UrlRoutingModule类型的Init()方法。
HttpHandler与HttpModule区别
HttpHandler,Http请求的处理者 例如ScriptHandler、WebServiceHandler,IHttpHandler的实现都是为了处理某一类的请求。如ScriptHandler负责处理对脚本的请求。
HttpModule,Http模块。实际上就是那19个标准事件的处理者,或者说19个标准事件的订阅者
一、HttpHandler的职责 应该这样理解HttpHanlder:一个HttpHanlder用于响应一类的请求,为一类的请求生成响应结果。
我们经常用到的HttpHanlder有哪些?
1. aspx页面。
2. asmx服务文件。
3. ashx文件(一般处理程序)。
4. 实现IHttpHandler接口的自定义类型。
二、HttpModule的职责
有时候有些页面需要一些相同的检查功能,比如身份验证。明显使用HttpHandler是不方便的,因为不是所有的页面都需要去调用那些相同的功能。
HttpModule的设计正是提供了一个灵活的方法解决这种功能重用的问题,它采用事件(观察者)的设计模式,将某些HttpHandler都需要的功能抽取出来,形成不同的观察者类型,这些观察者类型可以编译成类库形式,供多个网站共用。
配置只是告诉ASP.NET,这些HttpModule需要运行起来,可能会用得着。
我们用HttpModule做什么事情?
1. 修改某些请求(例如前面的示例修改了响应头)。
2. 检查检查请求(例如身份认证检查)。
HttpModule能处理哪些请求呢?
1. 默认是全部进入ASP.NET的请求。
2. 如果只需要处理部分请求,那么请自行判断。
总结: HttpHandler(中文:处理程序)相当于一条水管,HttpModule相当于一小节水管。HttpHandler有很多条,一条流油,一条流水等等。HttpModule(中文:http模块)相当于一小截,需要过滤的长水管里面都可以装上。HTTP Module是特殊类型的类,它参与每一次页面请求。
附 mvc 代码:
PostResolveRequestCache:
public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);
if (routeData != null)
{
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
}
RequestData data2 = new RequestData();
data2.OriginalPath = context.Request.Path;
data2.HttpHandler = httpHandler;
context.Items[_requestDataKey] = data2;
context.RewritePath("~/UrlRouting.axd");
}
}
}
普通asp.net应用程序生命周期:
HttpApplication对象是Asp.net中处理请求的重要对象,但是,这种类型的对象实例不是由程序员来创建,而是由Asp.net帮助我们创建。为了便于扩展处理,Asp.net暴露了大量的事件给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以自定义每一个请求的扩展处理过程。
HttpApplication的19个标准事件如下:
事件名称 | 说明 |
BeginRequest | Asp.net处理的第一个事件,表示处理的开始 |
AuthenticateRequest | 验证请求,一般用来取得请求用户的信息 |
PostAuthenticateRequest | 已经获取请求用户的信息 |
AuthorizeRequest | 授权,一般用来检查用户的请求是否获得权限 |
PostAuthorizeRequest | 用户请求已经得到授权--这里开始每个页面触发一次,包括刷新 |
ResolveRequestCache | 获取以前处理缓存的处理结果,如果以前缓存过,那么,不必再进行请求的处理工作,直接返回缓存结果 |
PostResolveRequestCache | 已经完成缓存的获取操作 |
PostMapRequestHandler | 已经根据用户的请求,创建了处理请求的处理器对象 |
AcquireRequestState | 取得请求的状态,一般用于Session --这里缓存页多用户只触发一次 |
PostAcquireRequestState | 已经取得了Session |
PreRequestHandlerExecute | 准备执行处理程序 |
PostRequestHandlerExecute | 已经执行了处理程序 |
ReleaseRequestState | 释放请求的状态 |
PostReleaseRequestState | 已经释放了请求的状态 |
UpdateRequestCache | 更新缓存 |
PostUpdateRequestCache | 已经更新了缓存 |
LogRequest | 请求的日志操作 |
PostLogRequest | 已经完成了请求的日志操作 |
EndRequest | 本次请求处理完成 |
其余的事件则处理应用程序请求,这些事件被触发的 顺序是:
Application_BeginRequest
Application_AuthenticateRequest
Application_AuthorizeRequest
Application_ResolveRequestCache
Application_AcquireRequestState
Application_PreRequestHandlerExecute
Application_PreSendRequestHeaders
Application_PreSendRequestContent
<<执行代码>>
Application_PostRequestHandlerExecute
Application_ReleaseRequestState
Application_UpdateRequestCache
Application_EndRequest
这些事件常被用于安全性方面。