WapModule.cs:
public class WapModule:IHttpModule
{
   public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }

// 处理BeginRequest 事件的实际代码
      void context_BeginRequest(object sender, EventArgs e)
        {
         ...............//todo:进入首页前的处理代码
     //eg:获得上下文
     //HttpApplication application = (HttpApplication)sender;
     //HttpContext context = application.Context;

}
   public void Dispose()
        {

}
}
Web.config:
<system.web>
<httpModules>
      <add name="MyModule" type="myWeb.WapModule"/>
</httpModules>   
</system.web>
这样假设将网站的首页设置为Default.aspx,访问Default.aspx页面时,在进入Default.aspx页面的代码之前会先进入WapModule.cs,然后根据WapModule.cs中的代码动态跳转到制定首页及记录一些访问者的机器信息等操作;

==============分割线======================

技术点:

(一)ASP.NET对请求处理的过程:

  当请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给ASPNET_ISAPI.dll,ASPNET_ISAPI.dll会通过http管道(Http PipeLine)将请求发送给ASPNET_WP.exe进程,在ASPNET_WP.exe进程中通过HttpRuntime来处理这个请求,处理完毕将结果返回客户端。

  inetinfo.exe进程:是www服务的进程,IIS服务和ASPNET_ISAPI.DLL都寄存在此进程中。

  ASPNET_ISAPI.DLL:是处理.aspx文件的win32组件。其实IIS服务器是只能识别.html文件的,当IIS服务器发现被请求的文件是.aspx文件时,IIS服务器将其交给aspnet_isapi.dll来处理。

  aspnet_wp.exe进程:ASP.NET框架进程,提供.net运行的托管环境,.net的CLR(公共语言运行时)就是寄存在此进程中。

  ASP.NET Framework处理一个Http Request的流程:

  
HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication
Factory-->HttpApplication-->HttpModule-->HttpHandler
Factory-->HttpHandler-->HttpHandler.ProcessRequest()

  ASP.NET请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,ASP.NET把
http请求依次传递给管道中各个HttpModule,最终被HttpHandler处理,处理完成后,再次经过管道中的HTTP模块,把结果返回给客
户端。我们可以在每个HttpModule中都可以干预请求的处理过程。

  注意:在http请求的处理过程中,只能调用一个HttpHandler,但可以调用多个HttpModule。

  

(二)HttpModule

  httpModules作用:

  当请求到达HttpModule的时候,系统还没有对这个请求真正处理,但是我
们可以在这个请求传递到处理中心(HttpHandler)之前附加一些其它信息,或者截获的这个请求并作一些额外的工作,也或者终止请求等。在
HttpHandler处理完请求之后,我们可以再在相应的HttpModule中把请求处理的结果进行再次加工返回客户端。

  HTTP模块是实现了System.Web.IhttpModule接口的类。

  IHttpModule接口的声明:

  public interface IHttpModule

  {

  void Init (HttpApplication context);

  void Dispose ();

  }

  Init 方法:系统初始化的时候自动调用,这个方法允许HTTP模块向HttpApplication 对象中的事件注册自己的事件处理程序。

  Dispose方法: 这个方法给予HTTP模块在对象被垃圾收集之前执行清理的机会。此方法一般无需编写代码。

  HTTP模块可以向System.Web.HttpApplication对象注册下面一系列事件:

  AcquireRequestState 当ASP.NET运行时准备好接收当前HTTP请求的对话状态的时候引发这个事件。

  AuthenticateRequest 当ASP.NET 运行时准备验证用户身份的时候引发这个事件。

  AuthorizeRequest 当ASP.NET运行时准备授权用户访问资源的时候引发这个事件。

  BeginRequest 当ASP.NET运行时接收到新的HTTP请求的时候引发这个事件。

  Disposed 当ASP.NET完成HTTP请求的处理过程时引发这个事件。

  EndRequest 把响应内容发送到客户端之前引发这个事件。

  Error 在处理HTTP请求的过程中出现未处理异常的时候引发这个事件。

  PostRequestHandlerExecute 在HTTP处理程序结束执行的时候引发这个事件。

  PreRequestHandlerExecute 在ASP.NET开始执行HTTP请求的处理程序之前引发这个事件。在这个事件之后,ASP.NET 把该请求转发给适当的HTTP处理程序。

  PreSendRequestContent 在ASP.NET把响应内容发送到客户端之前引发这个事件。这个事件允许我们在内容到达客户端之前改变响应内容。我们可以使用这个事件给页面输出添加用于所有页面的内容。例如通用菜单、头信息或脚信息。

  PreSendRequestHeaders 在ASP.NET把HTTP响应头信息发送给客户端之前引发这个事件。在头信息到达客户端之前,这个事件允许我们改变它的内容。我们可以使用这个事件在头信息中添加cookie和自定义数据。

  ReleaseRequestState 当ASP.NET结束所搜有的请求处理程序执行的时候引发这个事件。

  ResolveRequestCache 我们引发这个事件来决定是否可以使用从输出缓冲返回的内容来结束请求。这依赖于Web应用程序的输出缓冲时怎样设置的。

  UpdateRequestCache 当ASP.NET完成了当前的HTTP请求的处理,并且输出内容已经准备好添加给输出缓冲的时候,引发这个事件。这依赖于Web应用程序的输出缓冲是如何设置的。

  上面这么多的事件,我们看起来可能会有些眼晕,但没关系,下面一步一步地看。

  HttpModule生命周期示意图

  下面是事件的触发顺序:

  BeginRequest和PreRequestHandlerExecute之间的事件是在服务器执行HttpHandler处理之前触发。

  PostRequestHandlerExecute和PreSendRequestContent之间的事件是在服务器执行Handler处理之后触发。

(三)下面我们看一下如何使用HttpModule来实现我们日常的应用:

  HttpModule通过在某些事件中注册,把自己插入ASP.NET请求处理管道。当这些事件发生的时候,ASP.NET调用对相应的HTTP模块,这样该模块就能处理请求了。

  1、向每个页面动态添加一些备注或说明性的文字:

  有的网站每一个页面都会弹出一个广告或在每个页面都以注释形式(<!-- -->)加入网站的版权信息。如果在每个页面教编写这样的JS代码的话,对于大一点的网站,这种JS代码的编写与维护可是一个很繁琐枯燥的工作。

  有了HttpModule我们就可以很简单地解决这个问题了。HttpModule是客户端发出请求到客户端接收到服务器响应之间的一段必经之
路。我们完全可以在服务器处理完请求之后,并在向客户端发送响应文本之前这段时机,把这段注释文字添加到页面文本之后。这样,每一个页面请求都会被附加上
这段注释文字。

  这段代码究竟该在哪个事件里实现呢? PostRequestHandlerExecute和PreSendRequestContent之间的任何一个事件都可以,但我比较喜欢在EndRequest事件里编写代码。

  第一步:创建一个类库ClassLibrary831。

  第二步:编写一个类实现IHttpModule接口

  class TestModule:IHttpModule

  {

  public void Dispose()

  {

  }

  public void Init(HttpApplication context)

  {

  }

  }

  第三步:在Init事件中注册EndRequest事件,并实现事件处理方法

  class TestModule:IHttpModule

  {

  public void Dispose(){}

  public void Init(HttpApplication context)

  {

  context.EndRequest += new EventHandler(context_EndRequest);

  }

  void context_EndRequest(object sender, EventArgs e)

  {

  HttpApplication ha = (HttpApplication)sender;

  ha.Response.Write("<!--这是每个页面都会动态生成的文字。--grayworm-->");

  }

  }

  第四步:在Web.Conofig中注册一下这个HttpModule模块

  <httpModules>

  <add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>

  </httpModules>

  name:模块名称,一般是类名

  type:有两部分组成,前半部分是命名空间和类名组成的全名,后半部分是程序集名称,如果类是直接放在App_Code文件夹中,那程序名称是App_Code。

  这样在Web站点是添加该类库的引用后,运行每个页面,会发现其源文件中都会加入“<!--这是每个页面都会动态生成的文字。--grayworm-->”这句话。同样的方法你也可以在其中加入JS代码。

  2、身份检查

  大家在作登录时,登录成功后,一般要把用户名放在Session中保存,在其它每一个页面的Page_Load事件中都检查Session中是否存在用户名,如果不存在就说明用户未登录,就不让其访问其中的内容。

  在比较大的程序中,这种做法实在是太笨拙,因为你几乎要在每一个页面中都加入检测Session的代码,导致难以开发和维护。下面我们看看如何使用HttpModule来减少我们的工作量

  由于在这里我们要用到Session中的内容,我们只能在AcquireRequestState和PreRequestHandlerExecute事件中编写代码,因为在HttpModule中只有这两事件中可以访问Session。这里我们选择PreRequestHandlerExecute事件编写代码。

  第一步:创建一个类库ClassLibrary831。

  第二步:编写一个类实现IHttpModule接口

  class TestModule:IHttpModule

  {

  public void Dispose()

  {

  }

  public void Init(HttpApplication context)

  {

  }

  }

  第三步:在Init事件中注册PreRequestHandlerExecute事件,并实现事件处理方法

class AuthenticModule:IHttpModule

  {

  public void Dispose(){}

  public void Init(HttpApplication context)

    {

      context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);

    }

  void context_PreRequestHandlerExecute(object sender, EventArgs e)

    {

      HttpApplication ha = (HttpApplication)sender;

      string path = ha.Context.Request.Url.ToString();

      int n = path.ToLower().IndexOf("Login.aspx");

  if (n == -1) //是否是登录页面,不是登录页面的话则进入{}

    {

      if (ha.Context.Session["user"] == null) //是否Session中有用户名,若是空的话,转向登录页。

    {

  ha.Context.Response.Redirect("Login.aspx?source=" + path);

    }

    }

  }

  }

第四步:在Login.aspx页面的“登录”按钮中加入下面代码

protected void Button1_Click(object sender, EventArgs e)

  {

    if(true) //判断用户名密码是否正确

   {

  if (Request.QueryString["source"] != null)

    {

      string s = Request.QueryString["source"].ToLower().ToString(); //取出从哪个页面转来的

      Session["user"] = txtUID.Text;

      Response.Redirect(s); //转到用户想去的页面

    }

  else

    {

      Response.Redirect("main.aspx"); //默认转向main.aspx

    }

   }

 }

第五步:在Web.Conofig中注册一下这个HttpModule模块

  <httpModules>

  <add name="TestModule" type="ClassLibrary831.TestModule,ClassLibrary831"></add>

  </httpModules>

  3、多模块的操作

  如果定义了多个HttpModule,在web.config文件中引入自定义HttpModule的顺序就决定了多个自定义HttpModule在处理一个HTTP请求的接管顺序。

httpModules与httpHandlers之httpModules(转载)的更多相关文章

  1. .Net程序员必须要知道的东西之HttpModules与HttpHandlers介绍

    一.ASP.NET对请求处理的过程: 当客户端请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给ASPNET_ISAPI. ...

  2. (翻译)从底层了解ASP.NET体系结构 [转]

    转自:http://www.cnblogs.com/rijing2004/archive/2007/09/14/howaspnetwork.html 前言 关于ASP.NET的底层的工作机制,最近园子 ...

  3. 关于httpHandlers、handlers和httpModules、modules的那些配置中的各种问题

    在web.config中配置httpHandlers.handlers和httpModules.modules根据服务器环境不同设置各有不同 在IIS6及IIS7.0以上的经典模式中配置httpMod ...

  4. ASP.NET底层与各个组件的初步认识与理解 (转载)

    ASP.NET底层的初步认识与理解   最近在国外的网站乱走一通,发现一些比较好的文章,收集整理加于自己的理解,作为笔记形式记录下来,让以后自己有个回忆. ASP.NET是一个非常强大的构建Web应用 ...

  5. web.config详解(转载)

    该文为转载 原文地址:http://www.cnblogs.com/gaoweipeng/archive/2009/05/17/1458762.html 花了点时间整理了一下ASP.NET Web.c ...

  6. [转载]IIS7报500.23错误的解决方法

    原文出处: 原文作者:pizibaidu 原文链接:http://pizibaidu.blog.51cto.com/1361909/1794446 背景:今天公司终端上有一个功能打开异常,报500错误 ...

  7. WebConfig配置文件详解(转载自逆心的博客)

    <?xml version="1.0"?> <!--注意: 除了手动编辑此文件以外,您还可以使用 Web 管理工具来配置应用程序的设置.可以使用 Visual S ...

  8. 如何在IIS6,7中部署ASP.NET网站(转载)

    查看web.config文件 web.config通常会放在网站的根目录,这个文件中包含了一最重要的网站运行参数.比如: connectionStrings,httpHandlers,httpModu ...

  9. C# Web.config 配置handlers 和 httpHandlers

    <system.web> <httpHandlers> <add verb="*" path="*.js.axd" type=&q ...

随机推荐

  1. Javascript本质第二篇:执行上下文

    在上一篇文章<Javascript本质第一篇:核心概念>中,对Javascript执行上下文做了解释,但是这些都是基于Javascript标准中对执行上下文的定义,也就是说理论上的东西,本 ...

  2. docker-8 docker小技巧

    docker使用小技巧 杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有的已经停止的容器 docker rm $(docker ps -a -q) 删除所 ...

  3. Codeforces 747C:Servers(模拟)

    http://codeforces.com/problemset/problem/747/C 题意:有n台机器,q个操作.每次操作从ti时间开始,需要ki台机器,花费di的时间.每次选择机器从小到大开 ...

  4. EF架构~充血模型设置不被持久化的属性

    回到目录 在Poco实体中,一般只有属性没有方法,这在软件设计中称为贫血模型,而在DDD领域驱动设计中,比较提倡充血模型,即你的Poco实体中,即有属性,也有操作属性的方法,注意这里说的是操作属性的方 ...

  5. C. Tavas and Karafs 二分查找+贪心

    C. Tavas and Karafs #include <iostream> #include <cstdio> #include <cstring> #incl ...

  6. bzoj2395

    分组赛时学到的最小乘积生成树模型,感觉这个思路非常神,可以说是数形结合的经典问题 由于生成树有两个权值,我们把每个生成树的权值表示成点坐标(sa,sb) 显然我们知道,乘积最小,那么点必然落在下凸壳上 ...

  7. Android App的生命周期是什么

    怎么说呢 看Android一般指的是 Activity的生命周期, 关于app的生命周期, 有明白的大神请告诉我 上面这张图是 网上搜到的一张关于app生命周期的图, 在我看来, 其实就是一个Acti ...

  8. js实现网页打印分页打印

    web打印思路:html页面本身带有打印功能window.print() 但是在打印时又不能word模板的要求来打印不能满足打印需求.同时我们打印的数据有时候是动态变化的需要按模板来打印我的处理方式是 ...

  9. 【核心研究】消息队列_MessageQueue

    消息队列排队过程中的消息.这第一条消息将首先被处理.但假设消息本身指定要处理的时间.我们必须等待,直到时间的消息处理能力.新闻MessageQueue正在使用Message类的表示,队列中的邮件保存结 ...

  10. 【swift-总结】函数

    swift的函数在swift2中的使用改变了不少 /** *param: personName 參数 *returns: String为返回值 */ func sayHello(personName: ...