模块和处理程序之通过HttpModule和HttpHandler拦截入站HTTP请求执行指定托管代码模块

1、简介

大多数情况下,作为一个asp.net web开发对整个web应用程序的控制是十分有限的,我们的控制往往只能做到对应用程序(高层面)的基本控制。但是,很多时候,我们需要能够低级层面进行交互,例如:Web服务器如何处理入站的出站的Http请求,这就需要找到与iis交互的方法!

在Asp.Net推出之前,为了获得IIS这个级别的控制,必须创建和扩展ISAPI扩展或过滤器,但是如果使用这个方法,必须具备C和C++的知识,并需要知道如何创建本机的Win32 Dll,所以为了解决这个问题,ASP.NET提供了处理Http请求的两种方法:HttpMoudle和HttpHandler,这两种方法为ASP.NET的底层处理过程提供了独特的访问级别。

2、处理Http请求

在开始编写模块和处理程序之前,应该先了解IIS和Asp.Net是如何处理入站的Http请求,以及将我们的逻辑插入这些请求时,该用什么选项。IIS是入站HTTP请求的基本端点。从较高层面来看,它的工作是监听和验证入站的Http请求,然后把它们路由到合适的模块进行处理,再把结果返回给最初的请求者,ASP.NET是处理(IIS传送过来的HTTP请求)的模块之一,但是这些请求如何处理,则取决与IIS的版本。

(1)、IIS6和Asp.Net

IIS6将Asp.Net当成了可以处理HTTP请求的独立的模块,而不是将他当成整个IIS请求处理管道的一部分

(3)、IIS7、IIS8和Asp.Net

从IIS7开始,Asp.Net就被集成到了IIS请求处理管道之中,并且允许在管道中集成托管模块

(4)、Asp.Net处理请求

无论使用哪个版本的IIS,基本HTTP请求管道模型都有处理请求的两个核心机制:HttpMoudle和HttpHandler,Asp.Net使用这两个机制来处理入站Http请求,生成响应,并返回给客户端。

从上图可以看出,Asp.Net允许在管道中存在有多个模块以处理不同的请求,在入站请求通过各个模块后,就传送给HttpHandler,他负责处理请求。

注:尽管一个请求需要通过许多不同的模块,但只能由一个处理程序来处理,该处理程序负责给入站的Http请求创建响应,在处理程序执行完毕并生成响应后,就通过一系列后期模块将响应返回给客户端。

(5)、HttpMoudle

HttpMoudle是一些很简单的类,可以把它们插入到请求处理管道中,为此,他们要关联在处理Http请求时触发的一系列事件中。要创建HttpMoudle,可以创建一个派生于IHttpModule接口的类

代码如下:

namespace ZC.Utilities
{
    public class HttpExceptionModule : IHttpModule
    {
        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public void Init(HttpApplication context)
        {
            throw new NotImplementedException();
        }
    }
}

这个接口要实现两个方法:Init和Dispose。Dispose方法不多介绍,用于释放非托管资源,Init方法是实现HttpMoudle功能的主要方法,它有一个方法参数HttpApplication context。这个参数允许访问当前的HttpApplication环境,它用于封装在请求处理过程中触发的不同事件。下图列出了可以在Init方法中注册的事件,以及这些事件的执行顺序:

(6)、Demo

给每个页面上都添加文本,但是页面很多,所以这个时候通过HttpMoudle修改Http输出流,就是一种非常好的方式,代码如下:

Web.config

<?xml version="1.0" encoding="utf-8"?>

<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

    <httpModules>
      <add name="AppendMsg" type="Utils.AppendMsg, Utils" />
    </httpModules>
  </system.web>
</configuration>

AppendMsg.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Utils
{
    public class AppendMsg : IHttpModule
    {
        HttpApplication _application = null;
        public void Init(HttpApplication context)
        {
            _application = context;
            _application.EndRequest += AppendMsgMethod;
        }

        private void AppendMsgMethod(object obj,EventArgs args) {
            _application.Context.Response.Write(string.Format("Time is {0}", DateTime.Now.ToLocalTime()));
        }

        public void Dispose()
        {

        }
    }
}

注意web程序需要添加Utils的引用

查看源码如下:

<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>

</title></head>
<body>
    <form method="post" action="./WebForm3.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="Y+jLHJQqIdubeA4PeKlp73tJF/5kr6OGFtrvvOUxgE1PuiLiIeQS3d3CuoCU/FiS37xouTrBPHNkumgGNrWOOQXSa8ygtC5ttdbA2seVKgo=" />
</div>

<div class="aspNetHidden">

    <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="6C325D90" />
</div>
    <div>
    
    </div>
    </form>
</body>
</html>
Time is 2017/6/8 11:11:28

ok,所有的页面都做了同一个append操作。

(7)、HttpHandler

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace web
{
    /// <summary>
    /// Handler1 的摘要说明
    /// </summary>
    public class Handler1 : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

HttpHandler不同与HttpModule,主要有以下几点:

a、HttpHandler是请求管道的最后一战,是终点,而HttpModule则不是

b、HttpHandler必须映射为特定的扩展名,也就是说必须是以.ashx结尾的才能算是HttpHandler

HttpHandler实现IHttpHandler接口,该接口维护一个方法和一个属性分别是ProcessRequest()和IsReusable属性

ProcessRequest()方法:

用于处理入站的Http请求

这两句代码设置了在默认情况下,类模块会把内容类型改写为纯文本,然后把"Hello World"写入输出流.

IsReusable属性: 该属性告诉入站的Http请求是否可重用这个HttpHandler实例

(8)在IIS中映射文件扩展名

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏崔庆才的专栏

妈妈再也不用担心爬虫被封号了!手把手教你搭建Cookies池

5884
来自专栏技术博客

Asp.Net MVC3.0网站统计登录认证的在线人数

  对于一个网站来说,统计在线人数是一个很重要的工作。平时也发现很多的网站论坛等都有在线人数的显示。对于一个网站如果在线人数很多,用户看到了这么个数字也是很了不...

1292
来自专栏菩提树下的杨过

温故而知新:HttpApplication,HttpModule,HttpContext及Asp.Net页生命周期

IIS在接到一个新的http请求后,最终会调用asp.net_isapi.dll的ISAPI扩展(特指IIS6.0环境,iis7.0的应用程序池默认为集成方式,...

1975
来自专栏跟着阿笨一起玩NET

关于WinForm/Web如何使用缓存Cach

相对到期也称滑动到期:设置相对过期时间 指定时间内无访问会失效。(类似Session机制)

1461
来自专栏Laoqi's Linux运维专列

Redis的持久化-AOF

3208
来自专栏跟着阿笨一起玩NET

.Net下收发邮件第三方公共库

http://www.lumisoft.ee/lswww/download/downloads/Net/

1551
来自专栏kwcode

使用Cache缓存

存放位置:服务器内存,用于频繁访问且不轻易更改的内容缓存。 string CacheKey = "CT1"; //检索指定项, object objModel ...

3086
来自专栏码农阿宇

ASP.NET CORE入门之读取Json配置文件

首先新建一.net core控制台项目,命名为jsonReader ? 然后选中引用,选择NuGet包管理器,点击浏览引入mircosoft.aspnetcor...

3118
来自专栏.NET开发那点事

AServer - 基于Asp.net core Kestrel的超迷你http服务器

  AServer是基于ASP.NET Core Kestrel封装的一个超迷你http服务器。它可以集成进你的Core程序里,用来快速的响应Http请求,而不...

1371
来自专栏技术博文

redis配置详解

##redis配置详解 # Redis configuration file example. # # Note that in order to read ...

4055

扫码关注云+社区

领取腾讯云代金券