从来不用也从来不研究这事件.但为了写那种CGI式的接口不得已研究一下.

环境  W10 VS2017

测试方法:写一个实现IHttpModule接口的类,在Init方法中加载所有事件然后打出日志,看看事件执行顺序.

模块接口类需要在IIS中打开"模块"->添加"模块"后使用.或者在webconfig里添加模块节点也行.

事件执行结果如下:

  • 0在 ASP.NET 响应请求时作为 HTTP 执行管线链中的第一个事件发生。BeginRequest
  • 1 当安全模块建立用户标识时发生 AuthenticateRequest
  • 2 当安全模块已建立用户标识时发生。PostAuthenticateRequest
  • 3 当安全模块已验证用户授权时发生。AuthorizeRequest
  • 4 在当前请求的用户已获授权时发生。PostAuthorizeRequest
  • 5 在 ASP.NET 完成授权事件以使缓存模块从缓存中为请求提供服务后发生,从而绕过事件处理程序(例如某个页或 XML Web services)的执行。ResolveRequestCache
  • 6 在 ASP.NET 跳过当前事件处理程序的执行并允许缓存模块满足来自缓存的请求时发生。PostResolveRequestCache
  • 7 在选择了用来响应请求的处理程序时发生 MapRequestHandler
  • 8 在 ASP.NET 已将当前请求映射到相应的事件处理程序时发生。PostMapRequestHandler
  • 9 当 ASP.NET 获取与当前请求关联的当前状态(如会话状态)时发生。AcquireRequestState
  • 10 在已获得与当前请求关联的请求状态(例如会话状态)时发生。PostAcquireRequestState
  • 11 恰好在 ASP.NET 开始执行事件处理程序(例如,某页或某个 XML Web services)前发生。PreRequestHandlerExecute
  • 12 当引发未经处理的异常时发生 Error
  • 13 在 ASP.NET 事件处理程序(例如,某页或某个 XML Web service)执行完毕时发生。PostRequestHandlerExecute
  • 14 在 ASP.NET 执行完所有请求事件处理程序后发生。该事件将使状态模块保存当前状态数据。ReleaseRequestState
  • 15 在 ASP.NET 已完成所有请求事件处理程序的执行并且请求状态数据已存储时发生。PostReleaseRequestState
  • 16 当 ASP.NET 执行完事件处理程序以使缓存模块存储将用于从缓存为后续请求提供服务的响应时发生。UpdateRequestCache
  • 17 在 ASP.NET 完成缓存模块的更新并存储了用于从缓存中为后续请求提供服务的响应后,发生此事件。PostUpdateRequestCache
  • 18 恰好在 ASP.NET 为当前请求执行任何记录之前发生。LogRequest
  • 19 在 ASP.NET 处理完 System.Web.HttpApplication.LogRequest 事件的所有事件处理程序后发生。PostLogRequest
  • 20在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生。EndRequest
  • 21 恰好在 ASP.NET 向客户端发送 HTTP 标头之前发生。PreSendRequestHeaders
  • 22 恰好在 ASP.NET 向客户端发送内容之前发生。PreSendRequestContent

一共有25个事件,日志显示了23个.有2个未打出.

  Disposed // 在释放应用程序时发生.   ----也可以自己调用Dispose()方法来引发这个事件,最好在EndRequest事件里调用,调用之后应用程序对象就没有了.

  RequestCompleted// 当托管对象与已经释放的请求相关联时发生。  ----这个不知道怎么触发

为了让一个类的方法变成接口可以这样:(参考博客http://www.cnblogs.com/fish-li/archive/2011/09/05/2168073.html)

  1. 用IHttpModule模块: 在模块中动态调用这个类的方法.简单的讲就是根据URL地址找到类名和方法名,然后用"反射"调用它们,并且将上下文对象传给这方法.
  2. 用IHttpHandler处理: 方法同上.

  根据参考博客提出的建议,使用IHttpHandler方法好.这个问题我看了几遍博客才有些明白.

------疑惑在于一直想不清楚IHttpModule和IHttpHandler区别到底在哪里.为什么要提供这两接口.现在看来,需要从这管道处理事件的设计角度看,能找到原因.------

管道处理方式设计:

  既然设计处理事件,也就是说将一次HTTP请求的处理过程硬性规定为这些步骤,每个步骤用注册事件的方式来执行自定义操作.这些步骤制定的是否合理,需要问设计者.这些事件也会调整,以前版本ASP.NET并没有25个事件,好像是19个.这样看来,没有合理,只有不断调优.之前写贪吃蛇游戏,采用的是类似的方法,在蛇每移动一下这个时刻,分解为几个步骤,判断蛇的状态,然后执行相应代码.这样做有个好处就是容易扩展功能,比如要新加一个状态,只要找到合适的步骤,将方法注册到这步骤上就行了.当然,前提是这些步骤设计得"合理".

IHttpModule与IHttpHandler时机

   IHttpModule的作用是注册管道事件,"所有请求"都会被执行这个类里注册过的事件(这个可能是错的).而IHttpHandler是一个处理程序,它属于管道处理的其中一个环节.经过打印日志发现:    

在第11个事件之后,执行IHttpHandler  // (11 恰好在 ASP.NET 开始执行事件处理程序(例如,某页或某个 XML Web services)前发生。)PreRequestHandlerExecute

另外在第7个事件之后,执行IHttpHandlerFactory(这个用于指定使用哪个IHttpHandler,详见参考博客)  //  7 在选择了用来响应请求的处理程序时发生 MapRequestHandler

HttpApplication类管理事件处理

  HttpApplication类管理这些事件的运行,它有一个方法CompleteRequest();  /使 ASP.NET 跳过 HTTP 执行管线链中的所有事件和筛选并直接执行 EndRequest 事件

 如果在第一个事件,BeginRequest事件中调用这个方法.那么程序打印日志如下:

  • 0在 ASP.NET 响应请求时作为 HTTP 执行管线链中的第一个事件发生。BeginRequest
  • 18 恰好在 ASP.NET 为当前请求执行任何记录之前发生。LogRequest
  • 19 在 ASP.NET 处理完 System.Web.HttpApplication.LogRequest 事件的所有事件处理程序后发生。PostLogRequest
  • 20在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生。EndRequest
  • 21 恰好在 ASP.NET 向客户端发送 HTTP 标头之前发生。PreSendRequestHeaders
  • 22 恰好在 ASP.NET 向客户端发送内容之前发生。PreSendRequestContent

  第1个和最后5个事件触发了,而IHttpHandler 需要在第11个事件后触发,所以没机会,就没执行.这说明IHttpHandler是管道过程中的其中一个环节.

  管道事件可以跳过而不执行,那么如果是充分利用ASP.NET管道事件机制的系统,它的很多代码都在注册在各事件步骤,那么随意跳过肯定不行.因为不能保证其它模块注册的事件有机会执行.

如果完全不使用这些事件也不使用这些模块,只是"为了让一个类的方法变成接口",那么,事件可以一个也不注册.模块可以不加载.但处理程序IHttpHandler一定要的.

模块和处理程序映射设置(关于IIS模块详见:      https://docs.microsoft.com/en-us/iis/get-started/introduction-to-iis/introduction-to-iis-architecture          )

  在IIS中新建一个网站后,(集成模式.NET4.0).已经加载了很多模块和处理程序映射了.可以删除不需要的模块(如果是继承的,删除不掉,需要在IIS节点上打开"模块",然后选中模块,点解除锁定.再到站点中就可以删除了)

  重要的模块:

  StaticFileModule(默认,本机,继承)

    // 用于处理静态文件,html,js,css.等等 如果不加的话,静态文件访问不了.

  DirectoryListingModule(默认,本机,继承)

    // 目录浏览功能,如果不加将,允许目录浏览权限的地方看不到目录列表.现在几乎没人浏览网站下的目录.除非是个FTP

  DefaultDocumentModule(默认,本机,继承)

    // 默认文档,例如http://www.xx/home 这样的URL会显示默认的index.htm(如果设定这个默认文档的话).如果不加,则没这功能.必须输入全的 http://www.xx/home/index.html

  AnonymousAuthenticationModule(默认,本机,继承)

    // 匿名验证.如果不加,网页打不开,提示没权限401错误.并且会触发第2个管道事件(当安全模块已建立用户标识时发生 AuthenticateRequest)后,马上触发 18-22事件.效果如同调用了 CompleteRequest()

  重要的处理程序映射:

  StaticFile 请求路径: *  模块: StaticFileModule,DefaultDocumentModule,DirectoryListingModule 权限:读取,脚本 请求限制:读取

    // 如果没有这个映射:静态文件访问不了.提示找不到404

模块和处理程序的关系:

  究竟处理程序和模块间有没关系?

  A. 处理程序映射:(在IIS功能,"处理程序映射"双击打开)可以添加几种

    1."添加托管处理程序",这种会设定"请求路径","类型",请求路径可以是*,*.ext,*.ashx,还可有目录如/api/*.总之是一个路径规则,"类型"就是这个处理程序的类名(带命名空间),请求限制还可设定如何调用这个处理程序,一般不用勾选映射选项.设定好之后,凡是符合这种路径规则的请求,都会执行这个处理程序.程序类必是实现了IHttpHandler接口的.

    2."添加模块映射",这种会设定"请求路径",模块,在模块下拉列表中只有本机安装好的模块,如果要自己模块则需要在IIS根上双击模块->配置本机模块->注册这个地方添加.然后在站点的"模块"功能中添加这个本机模块后,下拉列表里才有.(我使用C#写的实现IHttpModule接口的类编译成DLL后,注册.发现没有效果.不知道是什么原因).

  以上两种设定,感觉如下,IHttpModule和IHttpHandler都能处理请求,并且可以让IHttpHandler处理程序负责某一类路径规则的所有请求(1),也可以为另一种路径规则的请求指定用哪些模块处理(2).

  那么也就是说模块也不再是针对所有请求的了,那么这个模块中注册的事件,也可以只是针对某一类请求的.(这可能是个误解,可能本机模块和托管模块有很大区别)

  B.模块:(在IIS功能,"模块")

    添加指托管模块(实现IHttpModule接口的),有一个选项"仅针对向ASP.NET应用程序或托管处理程序发出的请求调用".选中和不选中时有区别.如果选了,那么在请求静态文件时,发现模块并不执行,而请求某个处理程序时,模块才执行.如果没有选择,那么处理静态文件时,它也执行了.这表明模块注册的事件是针对所有请求都有效的.

    这个选项在于解决一个明显问题,就是"如果说模块是针对所有请求的"那么请求静态文件时,这个模块的功能也会执行,但是大多数情况下,静态文件就是直接发向客户端了,并不需要去执行模块里的事件.不需要经过管道处理.

  I.上述情况或许表明,托管模块或者处理程序在实际上都是针对某种请求而设计,并不需要一种接管所有请求的模块或者处理程序.至少静态文件和动态文件的处理是不同的,StaticFile这个模块映射使用的路径是*,表明它接管所有请求,并且使用DefaultDocumentModule,DirectoryListingModule,StaticFileModule这三个模块处理这些请求.那么其它路径规则应该是在它之前执行,如果都找不到才丢给它当做静态文件处理(猜测的).

  II.小结:

    托管模块IHttpModule注册的事件是针对所有请求的,但在添加时,可以选择只针对托管请求(或者说是指明了处理程序的请求).它的作用在于注意各种事件,并不具体处理请求和返回结果.(虽然也可以)

    处理程序IHttpHandler是若干事件中的一个步骤,是在11步之后执行的.它的重要工作是返回一个处理结果.并不需要关心自己在处理事件中的位置

  III.如果完全不使用这套处理管道机制,那么也就没必要用ASP.NET了.可以用System.Net.HttpListener这个类写一个监听程序然后挂上自己的C#程序.

为了让一个类的方法变成接口,可以:

  定制一个网站,只加载必要的模块和处理程序映射,然后将自己的类库项目,再弄一个web.config(这个可以方便配置模块与映射,而不需要在IIS控制台上配置)放到这网站目录中,执行程序放bin.web.config放根目录 ,这样就可行.

------------------------------------随时修正和补充-----------------------------------

asp.net处理事件的更多相关文章

  1. 如何确定asp.net请求生命周期的当前处理事件

    1 首先在全局应用程序里面添加如下代码 using System; using System.Collections.Generic; using System.Linq; using System. ...

  2. ABP(现代ASP.NET样板开发框架)系列之14、ABP领域层——领域事件(Domain events)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之14.ABP领域层——领域事件(Domain events) ABP是“ASP.NET Boilerplate P ...

  3. ASP.net 页面生命周期

    ASP.NET 页面生命周期 Page_Preinit(); 在页初始化开始时发生 Page_Init(); 在所有控件初始化且应用外观设置后引发 Page_InitComplete(); 在页初始化 ...

  4. 请求如何进入ASP.NET MVC框架

    一.前言 对于WebForm开发,请求通常是一个以.aspx结尾的url,对应一个物理文件,从代码的角度来说它其实是一个控件(Page).而在MVC中,一个请求对应的是一个Controller里的Ac ...

  5. .NET、C#和ASP.NET,ASP.NET MVC 四者之间的区别

    经常,会有一些人搞不清楚.NET和c#和ASP.NET这三者之间的关系,她们都是什么呢?他们之间有什么关系呢?总结一下 首先:什么是.NET? .NET是微软公司下的一个开发平台,.NET核心就是.N ...

  6. 【译】ASP.NET应用程序和页面生命周期

    为何翻译此文 一.此文是Code Project社区2010年4月ASP.NET板块的最佳文章,说明了此文的份量: 二.锻炼自己的英文技术文章翻译能力,提高英文技术文档阅读能力: 三.了解掌握ASP. ...

  7. ASP.Net请求处理机制初步探索之旅 - Part 1 前奏

    开篇:ASP.Net是一项动态网页开发技术,在历史发展的长河中WebForm曾一时成为了ASP.Net的代名词,而ASP.Net MVC的出现让这项技术更加唤发朝气.但是,不管是ASP.Net Web ...

  8. ASP.Net请求处理机制初步探索之旅 - Part 3 管道

    开篇:上一篇我们了解了一个ASP.Net页面请求的核心处理入口,它经历了三个重要的入口,分别是:ISAPIRuntime.ProcessRequest().HttpRuntime.ProcessReq ...

  9. [ASP.NET MVC 小牛之路]01 - 理解MVC模式

    本人博客已转移至:http://www.exblr.com/liam  PS:MVC出来很久了,工作上一直没机会用.出于兴趣,工作之余我将展开对MVC的深入学习,通过博文来记录所学所得,并希望能得到各 ...

随机推荐

  1. Python_编写UDP通信编解码类、文件的上传、远程执行命令、黏包

    1.UDP通信编解码类 (1) 类 # ------------------UDP通信解码编码类------------------------ from socket import * class ...

  2. python中类方法,实例方法,静态方法的作用和区别

      Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢?如何调用的呢?它们又有何区别和作用呢?且看下文. 首先,这三种方法都定义在类中.下面我先简单说一下怎么 ...

  3. flutter 动画双指放大图片

    class GridAnimation extends StatefulWidget { @override State<StatefulWidget> createState() { r ...

  4. re正则表达式-1

    匹配/查找/替换/分割函数: import re re.match('aa','aabbcc') 返回对象中span为开始位置和结束位置 re.match('aa','bbaacc') #返回值为No ...

  5. mktemp -t -d用法

    mktemp命令用于建立暂存文件或者文件夹,帮助文档如下: Usage: mktemp [OPTION]... [TEMPLATE] Create a temporary file or direct ...

  6. RN 实战 & React Native 实战

    RN 实战 & React Native 实战 https://abc.xgqfrms.xyz/react-native-docs/ 0.59 https://github.com/xgqfr ...

  7. 生成统计数据并导出Excel

    需求:看如下表格的统计需求 生产调度中心部门需要从IT技术部门得到这些统计数据 步骤: (1)获取所有的子公司列表 (2)遍历所有的子公司,获取每个子公司的库存信息 (3)遍历所有的库存信息,并对库存 ...

  8. 循环神经网络RNN及LSTM

    一.循环神经网络RNN RNN综述 https://juejin.im/entry/5b97e36cf265da0aa81be239 RNN中为什么要采用tanh而不是ReLu作为激活函数?  htt ...

  9. 注解方式过滤器(Filter)不能过滤Servlet的问题

    https://www.aliyun.com/jiaocheng/778495.html 今天写filter(过滤器)的时候,碰到一个奇怪的问题,发现filter可以过滤urlPatterns,但是无 ...

  10. 3.docker基础架构

    docker是一个典型的c/s架构产品. dockerd :为客户端提供  RESTFUL API,响应来自客户端的请求, 采用模块化的架构, 通过专门的 Engine 模块来分发管理各 个来自客户端 ...