当用户在浏览器输入一个URL地址后,浏览器会发送一个请求到服务器。这时候在服务器上第一个负责处理请求的是IIS。然后IIS再根据请求的URL扩展名将请求分发给不同的处理程序处理。

  流程如下:

  

当请求一个经由IIS进入到对应处理程序后:

从请求进入ASP.NET工作者进程,直至它到达最终的处理程序之前要经过一系列的步骤和过程,这个步骤和过程称为ASP.NET处理管道。

  Asp.net的处理管道流程如下:

  

  1. Asp.net处理管道的第一步是创建HttpWorkerRequest对象,它包含于当前请求有关的所有信息。
  2. HttpWorkerRequest把请求传递给HttpRuntime类的静态ProcessRequest方法。HttpRuntime首先要做的事是创建HttpContext对象,并用HttpWorkerRequest进行初始化。
  3. 创建了HttpContext实例之后,HttpRuntime类就通过调用HttpApplicationFactory的静态GetApplicationInstance()方法,为该应用程序请求HttpApplication派生类的一个示例。GetApplicationInstance()方法要么创建一个HttpApplication类的一个新实例,要么从应用程序对象池中取出一个实例。
  4. 在创建完成HttpApplication实例之后,就对它进行初始化,并在初始化期间分配应用程序定义的所有模块。
  5. 模块式实现IHttpModule接口的类,作用就是为了实现那经典的19个标准处理事件。
  6. 在创建了模块之后,HttpRuntime类通过调用它的BeginProcessRequest方法,要求最新检索到的HttpApplication类对当前请求提供服务。然后,为当前请求找到合适的处理程序工厂。
  7. 创建处理程序,传递当前HttpContext,一旦ProcessRequest方法返回,请求完成。

在HttpRuntime创建了HttpContext对象之后,HttpRuntime将随后创建一个用于处理请求的对象,这个对象的类型为HttpApplication。

在HttpApplication中,利用.Net中的事件机制,通过在处理过程中依次发出的多个事件,将这个处理过程分解为多个步骤,这个处理机制通常我们称为处理管道。MVC生命周一共分成19个事件。

HttpApplication的19个标准事件如下:(HttpRuntime维护着一个HttpApplication池,当有HTTP请求过来,从池中选取可用的HttpApplication处理请求,可见!HttpRuntime是入口)

HttpApplication有19个管道事件,分别是:

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:整个请求处理完成后触发该事件

我们可以在全局配置文件Global.asax中,按照约定的规则Application_{Event Name}来对管道事件定制:

HttpApplication提供了基于事件的扩展机制,允许程序员借助于处理管道中的事件进行处理过程扩展。由于HttpApplication对象是由Asp.net基础架构来创建和维护的,那么,如何才能获取这个对象的引用,以便于注册HttpApplication对象的事件处理,在Asp.net中,提供了两种方式来解决这个问题:IHttpModule方式和golbal.asax方式。这两种方式的核心都是IHttpModule接口。

IHttpModule接口的定义如下,其中仅仅包含两个成员:

public interface IHttpModule
{
void Dispose();
void Init(HttpApplication app)
}

  其中,Dispose方法用于回收Module所使用的非托管资源,如果没有的话,直接返回即可。

  最重要的是Init方法,可以看到,这个方法接收一个HttpApplication类型的参数,在Asp.net中,每当创建一个HttpApplication对象实例,将遍历注册的HttpModule类型,通过反射,依次每个注册HttpModule类型的一个实例对象,并将这个HttpApplication实例通过Init方法传递给各个HttpModule,这样HttpModule就可以在第一时间完成针对HttpApplication对象的事件注册了。

  例如:自定义一个Module


public class TestModule : IHttpModule
{
public void Dispose(){}
public void Init(HttpApplication app)
{
app.PostAcquireRequestState += new EventHandler(app_PostAcuiredRequestState);
app.PreRequestHandlerExecute += new EventHandler(app_PreRequestHandlerExecute);
} void app_PreRequestHandlerExecute(object sender, EventArgs e)
{
//TODO:
} void app_PostAcquiredRequestState(object sender, EventArgs e)
{
//TODO:
}
}

当某个请求与一个规则匹配后,ASP.NET会调用匹配的HttpHandlerFactory的GetHandler方法来获取一个HttpHandler实例, 最后由一个HttpHandler实例来处理当前请求,生成响应内容

所有的HttpHandlers都实现了IHttpHandler接口:

public interface IHttpHandler
{
bool IsReusable{get;}
void ProcessRequest(HttpContext context);
}

比如我们可以自定义一个HttpHandler来响应一类特定的请求:

public class Login : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string username = context.Request.Form["name"];
string password = context.Request.Form["password"]; if(password="sth")
{
System.Web.Security.FormsAuthentication.SetAuthCookie(username, false);
context.Response.Write("ok");
}
else
{
context.Response.Write("用户名和密码不正确");
}
}
}

global.asax中HttpApplication事件的自动注册

  在global.asax中,针对HttpApplication的事件处理,可以通过定义特殊命名的方法来实现。首先,这些方法必须符合System.EventHandler,因为所有的HttpApplication管道事件都使用这个委托定义。第二,方法的作用域必须是public。第三,方法的命名格式必须如下:Application_注册的事件名称。按照这种命名方法定义在global.asax中的方法将被自动注册到对应的事件中。

  例如,希望在global.asax中注册PostAuthenticateRequest事件处理,那么在global.asax中应该定义一个如下的方法:

    void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
Response.Write("验证通过事件!");
}

原文转载自:https://www.cnblogs.com/changrulin/category/725993.html 和 https://www.cnblogs.com/changrulin/p/4769353.html 和 https://www.cnblogs.com/kissdodog/p/3527379.html 和 https://www.cnblogs.com/kissdodog/p/3527922.html

MVC Request生命周期(综合总结)的更多相关文章

  1. SpringMVC request生命周期

    When the request leaves the browser, it carries information about what the user is asking for. At ve ...

  2. node.js WebService异常处理(domain)以及利用domain实现request生命周期的全局变量

    成熟的Web Service技术,例如Fast CGI.J2EE.php,必然会对代码异常有足够的保护,好的Web必然会在出错后给出友好的提示,而不是莫名其妙的等待504超时.而node.js这里比较 ...

  3. Erlang cowboy http request生命周期

    Erlang cowboy http request生命周期 翻译自: http://ninenines.eu/docs/en/cowboy/1.0/guide/http_req_life/ requ ...

  4. C# MVC 5 - 生命周期(应用程序生命周期&请求生命周期)

    本文是根据网上的文章总结的. 1.介绍 本文讨论ASP.Net MVC框架MVC的请求生命周期. MVC有两个生命周期,一为应用程序生命周期,二为请求生命周期. 2.应用程序生命周期 应用程序生命周期 ...

  5. javaBean Request生命周期

    request: 在request范围内,JavaBean对象的有效范围为: ① 客户请求访问的当前JSP页面② 和当前JSP页面共享同一个请求的页面,包括<%@ include%>指令以 ...

  6. .NET MVC页面生命周期及传统ASP.NET页面周期

    目前我主要使用.Net MVC框架进行网页创建,数据库是MSSQL Server.所以,我就用.NET MVC框架的web页面周期来说明页面的生命周期,但是我觉着其他MVC框架也是大同小异的. 本文主 ...

  7. 【MVC】ASP.NET MVC 请求生命周期

    当一个asp.net mvc应用程序提出请求,为了响应请求,包含一些请求执行流程步骤! 在asp.net mvc应用程序Http request和Http response 过程中,主要包含8个步骤: ...

  8. mvc的生命周期

    尽管每次都是从msdn里复制粘贴,但是还是有必要的,加深对mvc的理解和官方的表述. 了解 MVC 应用程序执行过程 发送给基于 ASP.NET MVC 的 Web 应用程序的请求首先通过 UrlRo ...

  9. MVC网址路由与生命周期

    这篇写得比较详细,所以我收藏一下. 转载自: http://www.cnblogs.com/Eleanore/archive/2012/11/23/2783061.html 一.网址路由 1.1  比 ...

随机推荐

  1. vue学习笔记(一)--Tab切换

    最近在学Vue,写的第一个demo是Tab,刚开始还直接把js代码贴过来改,没觉得有什么不同.然后请教别人说,用Vue最好不要操作dom啦,又把代码做了修改-_-. html代码如下: <div ...

  2. SpringBoot+Mybatis实现关联查询

    SpringBoot+Mybatis实现关联查询 今天学习了下Mybatis的动态查询,然后接着上次的Demo改造了下实现表的关联查询. 话不多说,开始今天的小Demo 首先接着上次的项目 https ...

  3. class中限定绑定属性__slots__方法

    使用__slots__但是,如果我们想要限制class的属性怎么办?比如,只允许对Student实例添加name和age属性.为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的 ...

  4. Python全栈开发记录_第八篇(模块收尾工作 json & pickle & shelve & xml)

    由于上一篇篇幅较大,留下的这一点内容就想在这里说一下,顺便有个小练习给大家一起玩玩,首先来学习json 和 pickle. 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过, ...

  5. C# 委托类型及使用

    转载声明:转载本文是为了方便自己查看,有需要的朋友建议查看原文(注:原文中有作者纠正的评论,我没有搬运)原文地址:http://www.cnblogs.com/akwwl/p/3232679.html ...

  6. Convert Adjacency matrix into edgelist

    Convert Adjacency matrix into edgelist import numpy as np #read matrix without head. a = np.loadtxt( ...

  7. Delphi Exif

    这久要用到读取JPG 的 Exif 信息,先是在盒子里下了个Demo,但是那个太老了,是2003年的,后来下载了个CCR 1.5.1是可以使用了,但是我个人用的是Delphi 2007,似乎CCR 1 ...

  8. oracle增加记录谁在连接你的数据库

    我们都知道在v$session 中记录着客户端的机器名称,但是没有IP , 如果记录clinet ip 呢? 有两种思路: ①    利用trigger,后面就是这种方式 ②    利用 DBMS_S ...

  9. 利用pyinstaller生成exe之后,运行不能正常产生结果文件问题记录

    https://segmentfault.com/q/1010000011284617/a-1020000011493026 在此链接已解决问题,现在在这里在详细记录一次 问题描述: 利用pychar ...

  10. sqlserver 使用游标过程中出现的错误

    下面的见解是在使用游标的过程中做的日记.我也是第一次使用,如果有什么不对的地方请批评指正,大家一起努力. 1. 消息 16951,级别 16,状态 1,过程 usp_proc,第 16 行      ...