ASP.NET使用管道模型(PipleLines)处理HTTP请求

大多数人认为ASP.NET仅仅只是页面——使用模板来创建HTML页面然后返回给浏览器。但是这仅仅只是ASP.NET使用HTTP管道模型处理WEB程序很小的一方面。管道模型是类似于Web Services的一种在服务器端处理ASP.NET页面的框架技术。作为一名高级的ASP.NET的开发者,你必须清楚管道模型是如何工作的。这篇文章就是解释和阐述HTTP管道模型是如何处理HTTP请求的。

一、管道对象模型

在System.Web的命名空间中处理HTTP的请求主要使用管道模型。一般的管道模型的结构如图-1。在管道模型开始运行前,HTTP的请求首先被传到HttpRuntime类的一个实例中,然后这个HttpRuntime的对象开始检查请求并找出这个请求被发送到的那个应用程序(在管道程序看来,一个虚拟目录就是一个应用程序)。然后管道模型就使用一个HttpApplicationFactory对象来找出或者创建一个HttpApplication对象来处理这个请求,一个HttpApplication可以包含一系列HTTP module对象(派生自IHttpModule接口)。HTTP modules作为一个过滤器可以在HTTP请求和响应信息穿过管道模型时检查和修改这些信息的内容。然后HttpApplication对象就使用HTTP handler factory来找出或产生一个HTTP handler对象。HTTP handlers是HTTP通信的最后一步,它主要用于处理请求信息(request)和响应信息(response)。注:HTTP handlers和 handler factory分别派生自IHttpHandler接口和IHttpHandlerFactory接口。

 

图-1

一个HttpApplication包括它的modules、handler在同一时刻只能处理一个Request请求。如果多重request请求同时到达一个相同的application时,多重HttpApplication对象将会被使用。

管道模型使用一个HttpContext对象去描述声明每一个成对的request/response信息。这个对象在HttpApplicaiton和handler之间来回传递。每一个module也能访问当前的HttpContext。HttpContext对象通过属性来描述声明HTTP的request和response信息(分别创建HttpRequest类和HttpResponse类的对象);同样,HttpContext对象也能通过属性来描述声明安全信息和每一个call、session和application。-2展示了部分HttpContext类常用的属性。

ASP.NET的HTTP管道模型是可扩展的,你可以实现自己的HTTP module、handler以及handler factory。你也可以直接继承HttpApplication类。

 

 

 

属性名

描述

Application

每一个application的request信息

Application Instance

正在处理request请求的Application对象

Cache

每一个application的缓存信息

Handler

正在处理request请求的Handler对象

Items

每一个request请求信息

Request

HTTP request 信息

Response

HTTP response 信息

Server

Utility functions

Session

Per-user cross-request state

User

User information

图-2:HttpContext类的常用属性

 

二、管道处理模型

ASP.NET的HTTP管道程序运行在IIS上来接收传递到进程中的request请求(被完整地传送到其他的web服务器上)。当IIS接收到一个HTTP的request请求时,它首先会通过目标URL检查文件的扩展名,如果文件的名被可执行代码关联,IIS就会调用这些代码来处理request请求。文件的扩展名被映射成可执行代码存储在IIS的metabase标记中。当ASP.NET被安装后,它会通过一个动态链接库aspnet_isapi.dll将各种不同的文件扩展名添加到matabase标记中,包括.apx和.asmx。

当IIS收到一个某一个页面文件发送的HTTP request请求时,它会调用aspnet_isapi.dll中的代码:使用一个命名管道将IIS服务器上的inetinfo.exe发送来的request请求转发到ASP.NET工作进程的一个实例:aspnet_wp.exe中。(在Windows Server 2003中, IIS 6.0kernel-mode模式的HTTP listener, 允许 request请求不通过inetinfo.exe而直接从操作系统转发到工作进程。)工作进程使用一个HttpRuntime类的实例来处理request请求。图-3 展示了完整的机制。

图-3

HTTP管道程序在工作进程的实例中处理request请求。默认地,在某一时刻仅仅只能有一个工作进程工作(如果你的web服务器有多个CPU,你可以配置管道程序使用多个工作进程),这是一个在本地IIS上很重要的一个改变,它使用不同的工作进程主要为了隔离不同的application程序。同时管道程序的各个工作进程也完全地被AppDomain所隔离,你可以将AppDomain看作是进程中的一个子进程。管道程序向一个AppDomain中的所有虚拟目录发送HTTP request请求。换句话说,每一个虚拟目录被作为一个单独的应用程序对待。这还有另外一个本地IIS值得注意的改变就是允许多个虚拟目录成为同一个application的一部分。
 ASP.NET支持基于很多标准的循环工作进程,这些标准包括空闲时间、requests serviced的数量、requests队列的数量以及物理内存的耗费量。全局.NET配置文件和machine配置文件初始化这些数值(好象processModel的元素)。当一个aspnet_wp.exe的实例 crosses one of these thresholds, aspnet_isapi.dll会运行一个新的工作进程并开始发送request请求。旧的实例在它处理完request请求后会自动终止。循环工作进程会提升可靠性通过在这些进程耗尽资源之前杀死它们。

三、HTTP Handlers

HTTP handlers 是一个继承自IHttpHandler接口的简单类,以下是该类的详细代码:

interface IHttpHandler

{

 // called to process request and generate response

 void ProcessRequest(HttpContext ctx);

 // called to see if handler can be pooled

 bool IsReuseable { get; }

}

Handlers也可以继承自IHttpAsyncHandler接口,如果想要它们支持异步调用。

HttpApplicaiton对象会调用ProcessRequest方法,通过handler来处理当前的HTTP请求和产生response响应。在此期间IsReuseable属性会被访问为类测定hanlder是否可以被再使用。

图-4的代码实现了一个简单的可以重用的HTTP句柄,它可以响应所有的request请求并返回当前的时间在一个XML标记中。你也可以使用使用HttpContext对象的response属性来设置response信息的MIME属性从而输出自己的内容。using System;
using System.Web;
 
namespace Pipeline
{
 
 public class TimeHandler : IHttpHandler
 {
    void ProcessRequest(HttpContext ctx)
    {
      ctx.Response.ContentType = "text/xml";
      ctx.Response.Write("<now>");
      ctx.Response.Write(
                   DateTime.Now.ToString());
      ctx.Response.Write("</now>");
    }
    bool IsReuseable { get { return true; } }
 }
}

图-4:TimeHandler


 

 

 

当HTTP handler类被实现时,它一定是被配置好的。配置会分为三个阶段:第一、你应该将编译好的代码放到ASP.NET工作进程能够找到的地方。一般地,已编译好的.NET文件(一般是dll文件)应该位于web服务器的虚拟目录下的bin文件夹中或位于全局编译缓存中(GAC)。

第二步:在HTTP request请求到来时,你应该让HTTP的管道程序执行你的代码。你可以通过在你虚拟目录下的web.config文件中去添加<httpHandlers>标签。如下:

<configuration>

 <system.web>

 <httpHandlers>

   <add verb="GET" path="*.time"

     type="Pipeline.TimeHandler,

     Pipeline"

   />

 </httpHandlers>

 </system.web>

</configuration>

   以上的代码可以作为附加的信息添加到.config的配置文件中。例如,这个web.config文件会告诉asp.net的HTTP管道程序处理所有.time文件的GET请求通过调用编译文件中的Pipeline.TimeHandler类。

最后,这些.time文件的request请求会被IIS转发到aspnet_isapi.dll,以便这些请求可以被管道程序第一时间处理。而且这些request请求也会在IIS的metabase中添加一个新的文件mapping映射。不过还有更简单的方式,就是直接使用IIS管理台将虚拟目录的文件扩展名映射到Application的配置对话框中。如图-5:

 

图-5

 

 

除了实现已有的客户端handler外,你也可以写自己的handler factoriey。一个handler factoriey就是一个实现了IHttpHandlerFactory的类。Handler factiory的配置方法和普通handlers一样,唯一不同的是原先web.config文件中的handler类都将被factory类所代替。

 

四、标准Handlers

    一些高级的ASP.NET技术,例如pages和Web Services都是通过顶层HTTP handler直接创建的。以下是通过.config文件来配置<httpHandlers>部分:

<httpHandlers> entries:

<httpHandlers>

 <add verb="*" path="*.ashx"

 type="System.Web.UI.SimpleHandlerFactory"

 />

 <add verb="*" path="*.aspx"

    type="System.Web.UI.PageHandlerFactory"

   />

   <add verb="*" path="*.asmx"

    type="System.Web.Services.Protocols.

    WebServiceHandlerFactory ... "

   />

 </httpHandlers>

    第一个实体映射扩展名为.ashx的文件到SimpleHandlerFactory类,使得一个HTTP handler factory知道如何从.ashx源文件中安装、编译和执行一个IHttpHandler。然后结果对象就可以被HTTP管道程序直接使用。

    图-6展示了使用.ashx文件重写的一个TimeHandler例子。@WebHandler部分告诉SimpleHandlerFactory Http handler类的名字在源代码编译后。这么做最大的好处就在它的配置非常简单:你只需要将所有的.ashx文件拷贝到虚拟目录下,而不需要再创建或修改web.config文件或在.NET安装完后再更新IIS。

<%@ WebHandler language="C#"
    class="Pipeline.TimeHandler" %>
 
using System;
using System.Web;
 
namespace Pipeline
{
 
 public class TimeHandler : IHttpHandler
 {
    void ProcessRequest(HttpContext ctx)
    {
      // set response message MIME type
      ctx.Response.ContentType = "text/xml";
      // write response message body
      ctx.Response.Write("<now>");
      ctx.Response.Write(
                   DateTime.Now.ToString());
      ctx.Response.Write("</now>");
    }
    bool IsReuseable { get { return true; } }
 }
}

图-6
 

第二个<httpHandlers>部分的实体将.aspx文件扩展名映射到PageHandlerFactory类,主要为了让HTTP handler factory知道如何将.aspx的源代码编译成一个System.Web.UI.Page-derived类。这个Page类实现了IHttpHandler借口,因此最终对象可以被HTTP管道程序直接使用。

第三个实体将.asmx的扩展名映射到WebServiceHandlerFactory类,这么做主要为了让一个HTTP handler factory知道如何将一个.asmx文件中的源代码编译并实例化。然后它会绑定一个标准的HTTP handler(默认的为SyncSessionlessHandler)实例并使用反射机制将SOAP信息转化成方法的调用参数。最后,最终对象就可以被HTTP管道程序直接使用了。
   这里需要值得注意的是PageHandlerFactory、WebServiceHandlerFactory和SimpleHandlerFactory类并不能在每一个request请求上都编译.aspx、.asmx和.ashx文件。作为替代,这些编译好的代码会被缓存在ASP.NET安装目录下的临时文件中。并且当源代码改变时,这些代码仅仅只会被编译一次。
 

五、HTTP Modules

    HTTP handlers是HTTP通信的最终部分。Handler类的实例专门用来接收HTTP请求并产生response响应。HTTP modules作为过滤器在request和response信息穿过管道程序时处理它们(可以是检查并修改这些信息的内容)。管道程序可以用这些HTTP modules特别安全地实现自己的底层处理程序。

HTTP modules 是实现IHttpModule接口的简单类:

interface IHttpModule

{

 // called to attach module to app events

 void Init(HttpApplication app);

 // called to clean up

 void Dispose()

}

当module被第一次创建时,Init方法会被HttpApplication对象调用,它可以通过HttpApplication对象将一个或多个事件handlers绑定到事件上。

图-7的代码展示了一个HTTP module如何处理HttpApplication对象的BeginRequest和EndRequest事件。在这个例子中,Init方法使用了常见的.NET技术将module的OnBeginRequst和OnEndRequest作为事件句柄绑定到HttpApplication对象上。OnBeginRequest主要作用是获取存储当前时间并将时间存放到变量start中。而OnEndRequest主要作用是计算OnBeginRequest和OnEndRequest之间的运行时间差并将这段时间添加到客户端HTTP header中。
 

OnEndRequest方法的最大优势在于第一个参数实际上传递的module绑定的HttpApplication对象。并且当前的信息会做为一个HttpApplication对象的属性(Http-Context)被OnEndRequest方法使用。

using System;
using System.Web;
 
namespace Pipeline
{
 
 public class ElapsedTimeModule : IHttpModule
 {
    DateTime start;
    public void Init(HttpApplication app)
    {
      // register for pipeline events
      app.BeginRequest +=
          new EventHandler(this.OnBeginRequest);
      app.EndRequest +=
          new EventHandler(this.OnEndRequest);
    }
    public void Dispose() {}
 
    public void OnBeginRequest(object o,
                               EventArgs args)
    {
      // record time when request started
      start = DateTime.Now;
    }
 
    public void OnEndRequest(object o,
                             EventArgs args)
    {
      // measure elapsed time
      TimeSpan elapsed =
              DateTime.Now - start;
 
      // get access to app and context
      HttpApplication app =
              (HttpApplication) o;
      HttpContext ctx = app.Context;
 
      // add custom header to HTTP response
      ctx.Response.AppendHeader(
                   "ElapsedTime",
                   elapsed.ToString());
    }
 }
}

图-7

在一个HTTP module类被实现和使用之间,必须对它做一定的配置。配置的步骤包括两步。首先你应该将编译好的module代码放到web服务器上的站点目录下的bin文件夹中以至于ASP.NET的工作进程能够找到它。
    然后你应该在你的web.config文件中添加<httpModules>部分,如下:

<configuration>

 <system.web>

 <httpModules>

   <add

    name="Elapsed"

    type="Pipeline.ElapsedTimeModule, Pipeline"

   />

 </httpModules>

 </system.web>

</configuration>

   这个例子中,web.config文件会告诉ASP.NET的HTTP管道程序将Pipeline.ElapsedTimeModule绑定到每一个HttpApplication对象用来处理这个虚拟目录下的service请求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode-SQL每日一练】——1.组合两个表

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦梦梦梦。小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的。想要掌握好…

【LeetCode-SQL每日一练】——2. 第二高的薪水

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的。想要掌握好SQL&am…

【LeetCode-SQL每日一练】—— 181. 超过经理收入的员工

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的。想要掌握好SQL&am…

【windows环境——VSCode安装教程】

大家好呀&#xff01;我是超梦&#xff0c;今天给小伙伴们带来一个最新版在windows环境的VSCode安装教程&#xff0c;话不多说我们开始吧。 VSCode安装下载与安装设置中文环境下载与安装 1. 第一步&#xff0c;进入官网&#xff0c;根据自己的电脑位数选择下载&#xff0c;小梦…

C#通用类Helper整理

★前言 最近下载了tita_chou在CSDN上传的一个资源&#xff0c;是在工作中整理的C#帮助类&#xff0c;里面包含了很多实用的类&#xff0c;想到我之前收集过自己用到少的可怜的类&#xff0c;心生敬意啊。当粗略的查看了那个资源&#xff0c;发现有一些是重复的&#xff0c;有一…

【LeetCode-SQL每日一练】—— 182. 查找重复的电子邮箱

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟【数据库】打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL【知识储备】是必不可少的。想要掌握…

【你会用代码画年兽吗】20行代码使用JS实现虎年春节倒计时 —— 红红火火过虎年

&#x1f34a;前言 &#x1f34a;哈喽小伙伴们好呀&#xff0c;我是超梦&#xff0c;大家可以叫我小梦~&#xff0c;马上就要过虎年春节啦&#xff0c;在新的一年里祝愿大家&#x1f42f;身体健康&#xff0c;&#x1f42f;平平安安&#xff0c;&#x1f42f;虎气冲天&#xf…

【LeetCode-SQL每日一题】——183. 从不订购的客户

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的。想要掌握好SQL&am…

c#进阶(1)—— Task Parallel Library 并行执行与串行执行

本文参考的博文出处&#xff1a;http://www.cnblogs.com/stoneniqiu/p/4857021.html 总体说明&#xff1a; &#xff08;1&#xff09;、理解硬件线程和软件线程 硬件线程也称为逻辑内核&#xff0c;一个物理内核可以使用超线程技术提供多个硬件线程。所以一个硬件线程并不代…

【leetcodeMySQL每周一练】- 5道题带你练习mysql

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的。想要掌握好SQL&am…

【读书笔记】.Net并行编程高级教程--Parallel

一直觉得自己对并发了解不够深入&#xff0c;特别是看了《代码整洁之道》觉得自己有必要好好学学并发编程&#xff0c;因为性能也是衡量代码整洁的一大标准。而且在《失控》这本书中也多次提到并发&#xff0c;不管是计算机还是生物都并发处理着各种事物。人真是奇怪&#xff0…

【除夕最炫烟花代码】—— HTML+JQuery实现2022跨年烟花特效

&#x1f387;前言 大家好呀&#xff01;我是小梦是✨。 除夕马上到来&#xff0c;激动的心颤动的手&#xff01;今年由于管控严厉&#xff0c;许多地方禁止燃放烟花爆竹&#xff0c;既然不让我们放&#xff0c;那我们就用代码来实现烟花特效&#xff01; 文末有彩蛋哦~ 烟花效…

【LeetCode-SQL每日一练】—— 595. 大的国家

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。大家可以叫我小梦~ 小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的…

c#进阶(2)—— ASP.NET MVC 常用路由总结

1、URL模式 路由系统用一组路由来实现它的功能&#xff0c;这些路由共同组成了应用系统URL架构或方案&#xff0c;这种URL架构是应用程序能够识别并能对之做出响应的一组URL&#xff0c;当处理一个输入 请求时&#xff0c;路由系统的工作是将这个请求URL与一个模式进行匹配&am…

【爱心代码大全】——情人节表白代码送给她属于我们程序员的浪漫

&#x1f474;大多数人以为的程序员——发量少&#xff0c;身穿格子褂&#xff0c;坐在电脑前就是码字。一点也不懂浪漫&#xff01; 谁说我们不懂浪漫的&#xff1f; 不&#xff01; 你错了 程序员一旦浪漫起来&#xff0c;真没其他人啥事了&#xff01;&#xff01;&#xff…

c#进阶(4)—— Redis 用于消息队列的存储

1、参考的博文 a : http://www.cnblogs.com/lori/archive/2012/04/12/2443708.html —— 主要的实现思路 b: http://www.cnblogs.com/liqingwen/archive/2017/04/06/6672452.html —— RedisHelper 类 c : https://www.cnblogs.com/stopfalling/p/5375492.html —— 应用场…

【LeetCode-SQL每日一练】—— 196. 删除重复的电子邮箱

&#x1f388;写在前面 &#x1f64b;‍♂️大家好呀&#xff0c;我是超梦。大家可以叫我小梦~ 小伙伴们都知道&#xff0c;不管是在学习中还是日常工作中&#xff0c;几乎天天是要跟数据库打交道的&#xff0c;为了更好的操作数据库&#xff0c;我们的SQL知识储备是必不可少的…

【情人节表白代码】——情人节将至,10余款浪漫爱心特效送给你爱的那个她

谁说我们不懂浪漫的&#xff1f; 不&#xff01; 你错了 程序员一旦浪漫起来&#xff0c;那就是个bug&#xff01;&#xff01;&#xff01; 浪漫表白一 代码部分 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/…

c#进阶(6)—— 网络通信基础知识

1、HttpClient 类 (1)、HttpClient 类 用于发送HTTP 请求&#xff0c;接收请求的响应。 (2)、HttpClient 类 派生于 HttpMessageInvoker类&#xff0c;此基类负责执行 SendAsync(),SendAsync() 方法调用是异步的&#xff0c;可以编写一个完全异步的系统来调用Web服务。 2、实…

【云原生】—— 学习云计算应用开发你需要掌握的五大技能

学习云计算应用开发之前&#xff0c;我们首先了解一下什么是云计算。 云计算百度百科&#xff1a;云计算&#xff08;cloud computing&#xff09;是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;…