小兵来谈asp.net 请求输入到输出的全过程 httpHandler和httpModuler

简介: 最近看了几篇讲述httpHandler和HttpModuler的文章,总的来说还是Fish li的那篇文章给力,但是他是大牛,他写出来的文章技术含量太高,对于像我这样的小兵, 要完全看懂估计需要看几遍。

最近看了几篇讲述httpHandler和HttpModuler的文章,总的来说还是Fish li的那篇文章给力,但是他是大牛,他写出来的文章技术含量太高,对于像我这样的小兵,

要完全看懂估计需要看几遍。虽然说没有完全了解底层操作,但是我也算明白了一个请求从进入IIS到最后输出都经历了哪些过程。说实话,原来我以为.Net的类的子

类都是设计者自己设计的,没有考虑到真正的程序员是否可以完全掌握。了解了底层操作,我发现我的那个观点是多么的无知,每个.Net的类都是对应现实中的一种对

象,比如说Mvc3 中的路由就包括RouteData和HttpContext,至于为什么要这样包含?只有了解了iis的触发过程,我们就会真正的了解了。

 

序言介绍完毕,现在就来分享一下我对IIS底层的理解。技术不过硬,只能是采用大白话来说。

 

上面这幅图说明了在IIS 6 下的处理过程。

 

 

因为我们现在所用的是MVC3  ,所以我就按照MVc3 中的生命周期来叙述一个请求从开始到消亡的全过程。

请求阶段:

 

  用户通过浏览器输入localhost/home/index 的地址,浏览器会发送一个请求到服务器的IIS用来处理这个请求。其实在操作系统中存在一个系统文件叫做http.sys

文件,它用来监视是否有请求到来,也就是说一个用户发来的请求的第一个接待者就是http.sys,它是一个系统文件,运行在操作系统的内核模式下,因此运行速度

更快。

 

在http.sys文件接收到请求之后(注:这是我的一个理解误区,我以前一直以为请求会直接进入IIS),会传入到第二个接待者IIS,真正的用来处理请求的操作系统组

件。在IIS接收到用户请求以后,首先会通过映射文件  然后由aspnet_iisapi.dll (IIS扩展)根据文件扩展名来选择对应的应用程序。这样说有点拗口,直白点的意思

就是IIS扩展会根据传入文件的扩展名(.aspx等)来选择 在IIS中配置的处理程序。这里会有一个问题存在,在Mvc中没有扩展名,那么程序是如何匹配的呢?其实这个

问题的处理方法有两种:

 

  1.就是通过在路由表中添加一个虚拟的扩展名来欺骗IIS

 

  2.就是通过在IIS配置文件中不选择确认文件存在,让IIS根据没有文件扩展名的文件路径来进行处理。

 

现在这个请求到了哪里?到了IIS扩展这里,下一步就是要进入到.Net框架中,让.Net框架来处理请求。但是在这中间会经过一些步骤的处理。大家应该记得在Web

form中有很多的事件,Page_load、Page_Render等,这些事件的执行顺序是依次进行的,不会混乱?那么.Net框架是如何来保证这些事件的顺序执行呢?这就是今

天的第一个主角HttpModule。我们可以把它称为http请求的过滤器,因为它不会有任何的输出,它会在任何请求中都会执行。当然有一个例外,那就是静态文件或者

其他没有配置为让IIS扩展让.Net框架处理的请求文件,因为他们进入到IIS中,IIS会找到对应的文件然后输出给浏览器的。

HttpModule的具体使用大牛们都说的很清楚了,我就简洁的描述一下大牛们忽略的知识点。既然说HttpModule是一个过滤器,那么我们可以在任何一个HttpModule

中终止当前请求的执行,执行身份认证,请问文件的访问权限检查等操作。我们可以自定义HttpModule扩展,只是让我们自己定义的类实现IHttpModule接口即可,

在IHttpModule  接口中有一个Init(HttpApplication app)方法,这是我们自定义扩展Module的入口,我们可以在其中定义我们自己进行的处理操作。

 

Init这个方法会接受一个HttpApplication类型的参数,HttpApplication 在MSDN中的定义就是定义 ASP.NET 应用程序中的所有应用程序对象通用的方法、属性和事

件。此类是用户在 global.asax 文件中所定义的应用程序的基类。HttpApplication 类的实例是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的。

HttpApplication 类的一个实例在其生存期内被用于处理多个请求,但它一次只能处理一个请求。这样,成员变量才可用于存储针对每个请求的数据。

 

看到这个类的定义我们有没有想到应用程序池的概念,在IIS中我们新建一个应用程序就会创建一个对应的应用程序池,其实在应用程序池中存储的是什么?应该就是

这些HttpApplication对象。每个请求会有一个对应的HttpApplication对象来全程的负责它的执行,在httpApplication对象中包含着请求所需要的所有参数值。例如

Response、Request、Cache等.Net常用的对象,甚至我们可以通过这个变量获取到web.config中定义的所有Module扩展。HttpApplication会伴随着请求的全部

执行过程。

 

现在一个问题又来了,这个Module扩展需要传递一个HttpApplication对象作为参数,那么这个方法的参数是由谁创建的呢?我们应该经常用到一个类

HttpRuntime,根据这个字面意思,我们也可以想到这个就是表示的Http运行时,是的,在IIS将请求的数据准备好以后会通过HttpRuntime 调用

HttpApplicationFactory的一个Create()方法来得到一个HttpApplication对象,然后把参数值传递给这个对象,最后这个对象会传递到Module扩展中。

 

 

现在请求经过了Module扩展过滤之后,就要进入到真正处理它的地方了,HttpHandler,提起它,如果我们有点陌生,那么我们一定使用过.Net中的一般处理程序,

我们可以看到一般处理程序是一个ashx文件,其中会继承自IHttpHandler接口,进行ProcessRequest处理。其实我们的HttpHandler就是ashx文件的codeBehind

文件。只要我们实现了IHttpHandler接口中的方法,就定义了一个Handler扩展。

 

HttpHandler 是作为处理者的角色出现的,不是过滤者,所以Handler会有输出结果。如果你要在Handler中使用Session,那么就要继承IRequiredSessionState

接口,或者加上一个IReadOnlySessionState接口,这样我们操作Session的时候才不会出现错误。在Handler中我们可以进行任何我们想要的操作,例如生成图片

水印、防盗链甚至是文件的输出压缩以及编码等都可以实现。

 

像我们的Web Service以及一般处理程序,从本质上说都是Handler的一种高层实现方式,都是进行了Handler的扩展操作。

 

因为我们讨论的是MVC,所以我们不得不考虑路由Route,其实Route是Mvc中的一个单独的组件,它在我们的整个请求中也占据了非常重要的地位。在IIS通过IIS扩

展选择了适当的处理程序来处理这个请求的时候,就是路由出现的时候,路由会根据路由配置分析这个路径的ControllerName以及ActionName,对应的参数值,然

后会把这些参数存储到RouteData中,RouteTable.Routes 是一个路由集合,RouteData和HttpContext上下文就会组成另一个类的对象,RequestContext,我

们在MVC编程的时候,经常会用到这个对象中的一些数据。.Net框架会根据RequestContext对象的值来匹配程序中的Controller以及Action,然后调用

ControllerDescriptor 执行Controller,生成Controller的对象,然后通过ActionInvoke方法来执行具体的Action。

 

在Action执行完毕,返回对应的视图的时候,整个请求在.Net框架中的处理就算结束了。在输出结果返回到用户浏览器之前,输出结果还会经过Module扩展的最后处

理,输出结果到达IIS,最后IIS通过Http.sys响应到用户浏览器上,用户就可以看到输出结果。

 

因为一个请求从进入到显示在浏览器上会两次经过Module扩展,这就是为什么我们在web form中可以定义一个开始事件,然后还会有一个完成事件的原因。

 

总结一下,一个用户发起的请求通过http.sys-->IIS-->aspnet_iisapi.dll-->对应的处理程序-->Module--->Handler-->Module--->IIS-->http.sys-->用户浏

览器。

 

当然这个请求的顺序不是特别的准确,因为省略了好多的细节,但是从大的方面说就是这些功能。可能你会有一个疑问,aspx文件没有是什么时候执行的呢?其实这

个问题我以前也有想过,aspx是在Module之后处理的,但是在handler之后还是之前呢?今天终于得到了答案,其实一个单独的aspx文件就是一个handler,每个

aspx文件在编译的时候都会编译成一个类,这个类继承自Page,但是Page继承自哪里呢?

public class Page : TemplateControl, IHttpHandler


我们可以看到Page继承自IHttpHandler接口,这就验证了Page类的执行是在Handler执行的时候触发的。

一个小小的http请求会让我们有那么多的知识要掌握,我们作为程序员对于这个请求的模型应该是很熟悉。但是作为.Net 拖控件开发的程序员,我善意的提醒一下,

如果可以不用控件,我们就别用了,用js、css来代替吧,毕竟html是基础。在Mvc时代到来的时候,,拥抱新技术吧。

 

我是小兵,没有太多的发言权,所以我就是按小兵的思路来分析大牛们的技术。

 

 

 

 

我又回来了,回到了技术最前线,
相关文章
|
开发框架 中间件 .NET
ASP.NET Core 请求处理管道
ASP.NET Core (请求处理管道) 了解ASP.NET处理管道为了理解ASP.NET Core中的请求处理管道概念,让我们修改Startup类的Configure()方法,如下所示。 在这里,我们将三个中间件组件注册到请求处理管道中。 如您所见,前两个组件是使用Use() 扩展方法注册的,因此它们有机会在请求处理管道中调用下一个中间件组件。 最后一个使用Run() 扩展方法注册,因...
45 0
ASP.NET Core 请求处理管道
|
关系型数据库 MySQL 数据库
找不到请求的 .Net Framework Data Provider。可能没有安装
做的一个项目,框架为.net framework 数据库为mysql 出现如标题错误 检查是否安装mysql、是否安装mysql connector net 笔者是因为没有安装后者mysql connector net 下载地址: [mysql connector net](https://downloads.mysql.com/archives/c-net/ "mysql connector net") 笔者安装截图如下: ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/c
227 0
【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。
【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。
831 0
【C#】【报错解决】找不到请求的Net Framework Data ProVider。可能没有安装。
|
3月前
|
开发框架 缓存 .NET
并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流
并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流
196 0
|
3月前
|
数据采集 JSON API
异步方法与HTTP请求:.NET中提高响应速度的实用技巧
本文探讨了在.NET环境下,如何通过异步方法和HTTP请求提高Web爬虫的响应速度和数据抓取效率。介绍了使用HttpClient结合async和await关键字实现异步HTTP请求,避免阻塞主线程,并通过设置代理IP、user-agent和cookie来优化爬虫性能。提供了代码示例,演示了如何集成这些技术以绕过目标网站的反爬机制,实现高效的数据抓取。最后,通过实例展示了如何应用这些技术获取API的JSON数据,强调了这些方法在提升爬虫性能和可靠性方面的重要性。
异步方法与HTTP请求:.NET中提高响应速度的实用技巧
|
1月前
|
API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
使用`System.Net.WebClient`类发送HTTP请求来调用阿里云短信API
21 0
|
3月前
|
数据采集 API 开发者
.NET 8新特性:使用ConfigurePrimaryHttpMessageHandler定制HTTP请求
在.NET 8中,通过`ConfigurePrimaryHttpMessageHandler`方法,开发者能更精细地控制HTTP请求,这对于构建高效爬虫尤为重要。此特性支持定制代理IP、管理Cookie与User-Agent,结合多线程技术,有效应对网络限制及提高数据采集效率。示例代码展示了如何设置代理服务器、模拟用户行为及并发请求,从而在遵守网站规则的同时,实现快速稳定的数据抓取。
.NET 8新特性:使用ConfigurePrimaryHttpMessageHandler定制HTTP请求
|
3月前
|
数据采集 开发框架 .NET
HttpClient在ASP.NET Core中的最佳实践:实现高效的HTTP请求
在现代Web开发中,高效可靠的HTTP请求对应用性能至关重要。ASP.NET Core提供的`HttpClient`是进行这类请求的强大工具。本文探讨其最佳实践,包括全局复用`HttpClient`实例以避免性能问题,通过依赖注入配置预设头部信息;使用代理IP以防IP被限制;设置合理的`User-Agent`和`Cookie`来模拟真实用户行为,提高请求成功率。通过这些策略,可显著增强爬虫或应用的稳定性和效率。
HttpClient在ASP.NET Core中的最佳实践:实现高效的HTTP请求
|
3月前
.NET Core 在其上下文中,该请求的地址无效。
.NET Core 在其上下文中,该请求的地址无效。
36 0
|
6月前
|
JSON 编解码 Go
Golang深入浅出之-HTTP客户端编程:使用net/http包发起请求
【4月更文挑战第25天】Go语言`net/http`包提供HTTP客户端和服务器功能,简化高性能网络应用开发。本文探讨如何发起HTTP请求,常见问题及解决策略。示例展示GET和POST请求的实现。注意响应体关闭、错误处理、内容类型设置、超时管理和并发控制。最佳实践包括重用`http.Client`,使用`context.Context`,处理JSON以及记录错误日志。通过实践这些技巧,提升HTTP编程技能。
76 1