当用户在浏览器输入一个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. OPNET下op_pk_copy()函数使用注意事项

    1)op_pk_copy()是生成新的数据包,函数op_pk_create_time_get()获取的是新数据包的生成时间.在统计数据包的端到端时延,以及服务时延需要注意. 2)此外发用数据包时使用o ...

  2. js通过formData上传文件,Spring后台处理

    1.前端 var formData = new FormData(); formData.append('file', $("#file").val()); $.ajax({ ur ...

  3. Maven 下载、安装、配置学习

    一.Maven 下载与安装 电脑已安装:JDK.Eclipse 1.下载Maven:http://maven.apache.org/download.cgi 2.解压并安装:解压路径名不能有中文! 3 ...

  4. Storm实现实时大数据分析(storm介绍,与Hadoop比较,)

    一.storm与Hadoop对比 Hadoop: 全量数据处理使用的大多是鼎鼎大名的hadoop或者hive,作为一个批处理系统,hadoop以其吞吐量大.自动容错等优点,在海量数据处理上得到了广泛的 ...

  5. Kafka(3)--kafka消息的存储及Partition副本原理

    消息的存储原理: 消息的文件存储机制: 前面我们知道了一个 topic 的多个 partition 在物理磁盘上的保存路径,那么我们再来分析日志的存储方式.通过 [root@localhost ~]# ...

  6. pyqt5 -—-布局管理

    绝对布局 例如: 我们使用move()方法定位了每一个元素,使用x.y坐标.x.y坐标的原点是程序的左上角. lbl1 = QLabel('Zetcode', self) lbl1.move(15, ...

  7. 进制与进制转换DAY2

    进制和进制转换 一.进制的基础 1.十进制(案例) 系数:0-9 进位规则:逢十进一 权:基数的次幂 基数:几进制基数就是几 规律:右侧第一位的权是10的0次幂,每向左移动一位次幂会+1. 进制的表示 ...

  8. Xilinx Zynq ZC-702 开发(01)—— 概览

    1.资料获取:https://github.com/Xilinx(开发所需资源,包括:交叉编译工具,linux kernel 源码,u-boot 源码, device-tree 源码,  qemu,  ...

  9. Linux gzip命令

    语法: gzip [-acdfhlLnNqrtvV][-S <压缩字尾字符串>][-<压缩效率>][--best/fast][文件...] 或 gzip [-acdfhlLnN ...

  10. 让新版appium支持by_name定位

    org.openqa.selenium.InvalidSelectorException: Locator Strategy 'name' is not supported for this sess ...