Asp.net管道模型之(HttpModules 和 HttpHandler)
上一节我们从大概范围介绍了管道模型的整体流程,我们从其中知道管道最重要的两大组件为:HttpModules 跟 HttpHandler。今天我们着重来介绍一下这两大组件
一:asp.net处理管道
从请求进入ASP.NET工作者进程,直至它到达最终的处理程序之前要经过一系列的步骤和过程,这个步骤和过程称为ASP.NET处理管道。
管道模型使用一个HttpContext对象去描述声明request/response信息。这个对象在HttpApplication和handler之间来回传递。HttpContext对象通过属性来描述request和response信息。下图展示了部分HttpContext类常用的属性。 
二:Module的详解
1:HttpModule:可以看做是一个拦截器,给我们在特定的事件处理请求的机会。HttpModule有很多应用,例如,我们要在每个请求的页面事件前加载Session数据,那么就用到SessionModule等等;
2:asp.net4.0提供了路由机制也是建立在一个UrlRouteModule上面的,它在请求映射到具体程序前拦截,然后重新映射。MVC又是建立在路由机制的基础上的。
3:怎么查看系统默认自带的Module以及怎么配置自定义的module。
A:打开C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config中的web.config,然后找到system.web节点下面的HttpModules下Module,一般系统自带的webconfig不要轻易去修改,因为这个是针对于全局的。如果要修改只需要修改自己项目中的webconfig

B:打开项目所在的webconfig,注释见下图:

4:怎么自定义module
右键 -》添加新项 --》选择Asp.net模块即自己定义的一个module已经创建完成。

module的注册一般都是在Init方法里面来完成的,整个过程分为以下几步:
- 当站点第一个资源被访问的时候,Asp.Net会创建HttpApplication类的实例,它代表着站点应用程序,同时会创建所有在Web.Config中注册过的Module实例。
- 在创建Module实例的时候会调用Module的Init()方法。
- 在Init()方法内,对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册,实际的方法需要另写)。
- HttpApplication在其应用程序周期中触发各类事件。
- 触发事件的时候调用Module在其Init()方法中注册过的方法。
- Dispose():它可以在进行垃圾回收之前进行一些清理工作
下面附上自己新定义的module代码:
public class CustomHttpModule : IHttpModule
{
public void Dispose()
{
Console.WriteLine();
} public event EventHandler CustomHttpModuleHandler; /// <summary>
/// 注册动作
/// </summary>
/// <param name="context"></param>
public void Init(HttpApplication application)
{
#region 为每一个事件,都注册了一个动作,向客户端输出信息
application.AcquireRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "AcquireRequestState "));
application.AuthenticateRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "AuthenticateRequest "));
application.AuthorizeRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "AuthorizeRequest "));
application.BeginRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "BeginRequest "));
application.Disposed += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "Disposed "));
application.EndRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "EndRequest "));
application.Error += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "Error "));
application.LogRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "LogRequest "));
application.MapRequestHandler += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "MapRequestHandler "));
application.PostAcquireRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostAcquireRequestState "));
application.PostAuthenticateRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostAuthenticateRequest "));
application.PostAuthorizeRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostAuthorizeRequest "));
application.PostLogRequest += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostLogRequest "));
application.PostMapRequestHandler += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostMapRequestHandler "));
application.PostReleaseRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostReleaseRequestState "));
application.PostRequestHandlerExecute += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostRequestHandlerExecute "));
application.PostResolveRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostResolveRequestCache "));
application.PostUpdateRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PostUpdateRequestCache "));
application.PreRequestHandlerExecute += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PreRequestHandlerExecute "));
application.PreSendRequestContent += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PreSendRequestContent "));
application.PreSendRequestHeaders += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "PreSendRequestHeaders "));
application.ReleaseRequestState += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "ReleaseRequestState "));
application.RequestCompleted += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "RequestCompleted "));
application.ResolveRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "ResolveRequestCache "));
application.UpdateRequestCache += (s, e) => application.Response.Write(string.Format("<h1 style='color:#00f'>来自MyCustomModule 的处理,{0}请求到达 {1}</h1><hr>", DateTime.Now.ToString(), "UpdateRequestCache "));
#endregion
}
}
自己定义的module已经完成,这样创建完成后,module还不会生效,如果想要其生效,需要在webconfig中的<system.webServer>(因为是该节点是针对于IIS中的集成模式)节点中配置:
<add name="CustomHttpModule" type="Ruanmou.MVC5.Utility.Pipeline.CustomHttpModule,Ruanmou.MVC5"/>
这样既可生效。具体详细配置见上面的第3点
另外还可以这样去新建module,然后注册方法如上配置webconfig,同样浏览的时候页面上面会看到module输出的信息:
public class ModuleDemo:IHttpModule
{
// Init方法仅用于给期望的事件注册方法
public void Init(HttpApplication context) {
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
} // 处理BeginRequest 事件的实际代码
void context_BeginRequest(object sender, EventArgs e) {
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
context.Response.Write("<h1 style='color:#00f'>来自HttpModule 的处理,请求到达</h1><hr>");
} // 处理EndRequest 事件的实际代码
void context_EndRequest(object sender, EventArgs e) {
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
context.Response.Write("<hr><h1 style='color:#f00'>来自HttpModule的处理,请求结束</h1>");
} public void Dispose() {
}
}
注意:module是针对于应用级,而不是页面级别的,即是只要注册module,则程序中所有的页面都会生效的!
5:怎么看当前请求中运用到了哪些module以及事件呢,可以通过下面代码来查看:
public ActionResult Module()
{
HttpApplication app = base.HttpContext.ApplicationInstance; #region 得到当前请求中所有的Event事件
List<SysEvent> sysEventsList = new List<SysEvent>();
int i = ;
foreach (EventInfo e in app.GetType().GetEvents())
{
sysEventsList.Add(new SysEvent()
{
Id = i++,
Name = e.Name,
TypeName = e.GetType().Name
});
}
#endregion #region 得到当前HttpApplication中所有的module,包括系统自带跟自己自定义的
List<string> list = new List<string>();
foreach (string item in app.Modules.Keys)
{
list.Add($"{item}: {app.Modules.Get(item)}");
}
#endregion ViewBag.Modules = string.Join(",", list);
return View(sysEventsList);
}
6:每个module的功能用途
|
名称 |
类型 |
功能 |
|
OutputCache |
System.Web.Caching.OutputCacheModule |
页面级输出缓存 |
|
Session |
System.Web.SessionState.SessionStateModule |
Session状态管理 |
|
WindowsAuthentication |
System.Web.Security.WindowsAuthenticationModule |
用集成Windows身份验证进行客户端验证 |
|
FormsAuthentication |
System.Web.Security.FormsAuthenticationModule |
用基于Cookie的窗体身份验证进行客户端身份验证 |
|
PassportAuthentication |
System.Web.Security.PassportAuthenticationModule |
用MS护照进行客户身份验证 |
|
RoleManager |
System.Web.Security.RoleManagerModule |
管理当前用户角色 |
|
UrlAuthorization |
System.Web.Security.UrlAuthorizationModule |
判断用户是否被授权访问某一URL |
|
FileAuthorization |
System.Web.Security.FileAuthorizationModule |
判断用户是否被授权访问某一资源 |
|
AnonymousIdentification |
System.Web.Security.AnonymousIdentificationModule |
管理Asp.Net应用程序中的匿名访问 |
|
Profile |
System.Web.Profile.ProfileModule |
管理用户档案文件的创立 及相关事件 |
|
ErrorHandlerModule |
System.Web.Mobile.ErrorHandlerModule |
捕捉异常,格式化错误提示字符,传递给客户端程序 |
三:管道中19个标准事件(每发一次都基本上会走下面的流程)
1:HttpHandler:可以看做一个处理器,它负责处理请求,输出数据。aspx,ashx或者说实现了IHttpHandler的都是HttpHandler。
2:系统的web.config配置的默认的对应的处理器。是根据后缀名然后映射到不同的处理器上面

随便找一个.aspx对应的handler,通过反编译会得到证实

3:自定义Handler处理器
3.1:右键新建项然后选择下图

3.2:然后具体代码如下:
public class CustomHandler : IHttpHandler
{
//MSDN上是这样解释的:获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例。也就是说后继的Http请求是不是可以继续使用实现了该接口的类的实例,一般来说,我把它设置成true。
public bool IsReusable => true; public void ProcessRequest(HttpContext context)
{
//Console.WriteLine("This is AAAA");
context.Response.Write("This is AAAA");
context.Response.ContentType = "text/html";
}
}
3.3:然后在 <system.webServer>节点下的 <handlers>增加如下:
<handlers>
<add name="rtmp" verb="*" path="*.rtmp" type="Ruanmou.MVC5.Utility.Pipeline.CustomHandler,Ruanmou.MVC5"/>
</handlers>
如果想要映射多个后缀可以:
<httpHandlers>
<add path="*.wss,*.rss" type=" 命名空间.类名,命名空间" verb="GET,POST," />
</httpHandlers>
注意:这里,path指的是请求的文件名称,可以使用通配符扩大范围,也可以明确指定这个handler仅用于处理某个特定的文件(比如说:filename.aspx)的请求。verb指的是请求此文件的方式,可以是post或get,用*代表所有访问方式。type属性由“,”分隔成两部分,第一部分是实现了接口的命名空间.类名,第二部分是位于Bin目录下的编译过的程序集名称。
3.4:最后在App_Start下面的RouteConfig里面配置一下路由过滤器,不然会一直走路由匹配:
routes.IgnoreRoute("CustomService/{*pathInfo}");//以CustomService开头,都不走路由
3.5:这样即可,可以在浏览器输入:

我们可以使用介个方式来做一个图片防盗链的功能。
4:系统自带默认的事件
注意:我们每次请求都会走下面的事件,然后会根据我们请求的后缀名然后去找对应的处理Handler,然后进行处理请求响应。

四:总结
MVC URLRouting Module对进入server的request进行了拦截,然后对request的handlerjinxingltes的处理。asp.net WebForm和asp.net MVC两者的不同,是在于最终使用的IHttpHandle的不同。WebForm中使用的是Page这个Handler,MVC中使用的是MVCHander。
Asp.net管道模型之(HttpModules 和 HttpHandler)的更多相关文章
- Asp.net管道模型(管线模型)
Asp.net管道模型(管线模型) 前言 为什么我会起这样的一个标题,其实我原本只想了解asp.net的管道模型而已,但在查看资料的时候遇到不明白的地方又横向地查阅了其他相关的资料,而收获比当初预 ...
- Asp.net管道模型(管线模型)之一发不可收拾
前言 为什么我会起这样的一个标题,其实我原本只想了解asp.net的管道模型而已,但在查看资料的时候遇到不明白的地方又横向地查阅了其他相关的资料,而收获比当初预想的大了很多. 有本篇作基础,下面两篇就 ...
- 关于asp.net mvc中的httpModules 与 httpHandler
ASP.NET对请求处理的过程: 当请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给ASPNET_ISAPI.dll,A ...
- ASP.NET-HTTP管道模型
HTTP管道模型处理WEB程序很小的一方面.管道模型是类似于Web Services的一种在服务器端处理ASP.NET页面的框架技术 一.管道对象模型 在System.Web的命名空间中处理HTTP的 ...
- ASP.Net 管道模型 VS Asp.Net Core 管道 总结
1 管道模型 1 Asp.Net Web Form管道 请求进入Asp.Net工作进程后,由进程创建HttpWorkRequest对象,封装此次请求有关的所有信息,然后进入HttpRuntime类进 ...
- ASP.NET管道模型简析
我相信在第一次听到这个名词时,有的小伙伴会一脸懵,而且还有很多疑问,其实我在第一次接触这个概念时跟很多小伙伴一样一脸懵. 接下来我将以我自己的理解来讲述什么是管道模型. 什么是管道模型 首先有没有小伙 ...
- asp.net管道模型
查了很多资料,终于大概弄懂管道模型(注意并非指定是asp.net范畴)是个什么概念了,其实就是从Unix移植过来的一种概念,也可以说是一种模式吧(只允许一头读,一头写,并且读完了就会自动消失). as ...
- Owin管道与asp.net管道模型
------2016.3.6 更新 文中提到没有Microsoft.Owin.Host.SystemWeb 这个dll 便不会加载Startup.Configuration,因为这个dll 其中有个O ...
- asp.net 管道模型+生命处理周期
http://www.cnblogs.com/qianlifeng/archive/2010/12/16/1908568.html https://msdn.microsoft.com/zh-cn/l ...
随机推荐
- python pip 升级 或者换源
1. 临时换源python -m pip install --upgrade pip -i https://pypi.douban.com/simple pip国内的一些镜像 阿里云 https ...
- MySQL MGR 集群从数据库显示RECOVRING
因为断电 或者 其他瞎折腾 导致: 从节点显示RECOVRING 查看错误日志显示: Slave SQL for channel 'group_replication_recovery': Error ...
- for循环结构
循环结构: 在程序当中总有一些需要反复/重复的执行的代码,假设没有循环结构,那么这段需要重复知心的需要重复执行的代码自然是需要重复编写的,代码无法得到重复使用.所以多数变成语言都是支持循环结构的.将来 ...
- Re-androideasy
题目地址 https://dn.jarvisoj.com/challengefiles/androideasy.apk.17e528e9498d4ae25dc82ad43730a03d 先看看功能 然 ...
- celery 异步发送短信验证码、延迟任务
短信 celery.py import os, django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "luffy ...
- Vue indent eslint缩进webstorm冲突解决
参考教程 官方回复 ESlint设置 rules: { 'no-multiple-empty-lines': [1, {max: 3}], // 控制允许的最多的空行数量 'vue/script-in ...
- Codeforces Round #551 (Div. 2) E 二分 + 交互
https://codeforces.com/contest/1153/problem/E 题意 边长为n的正方形里面有一条蛇,每次可以询问一个矩形,然后会告诉你蛇身和矩形相交有几部分,你需要在最多2 ...
- sql 合并结果集数据
起因:项目上查询一些数据,需要将查询后的结果合并到一列中. 1.STUFF函数 官方api: https://docs.microsoft.com/zh-cn/sql/t-sql/functions/ ...
- finalize()方法什么时候被调用?析构函数(finalization)的目的是什么?
链接:https://www.nowcoder.com/questionTerminal/d8eab06913084e42b515633604eef7cd?pos=28&mutiTagIds= ...
- mongodb创建管理员用户
db.createUser({user: "admin",pwd: "xxx",roles: ["root"]});