您的位置:首页 > 理论基础 > 计算机网络

HTTPModule vs HTTPHandler

2017-01-11 15:15 411 查看
直接上结论:

HTTPModule:任何请求都将先经过HTTPModule的处理;

HTTPHandler:要为请求构造Response时,将根据特定类型的请求调用相应的HTTPHandler。

一、ASP.NET Application Life Cycle Overview

先来看看ASP.NET应用程序的生命周期是怎样的。



当一个请求到来时,IIS将其分配给ASP.NET Engine,而后这个请求经由Application pipeline经过一系列处理,最终构造对于特定请求的响应,发送给Client。

重要的是这个pipeline。

二、Pipeline processed by HTTPApplication

当前戏做足了,ASP.NET将创建一个HTTPApplication实例,这个实例可以 reused by subsequent requests,因此为了性能考虑,可以只在第一次请求时被实例化。若工程中含有Global.asax文件,则将会创建从HTTPApplication类继承的子类的实例,在子类中你可以对pipeline中的这些event handler进行自定义处理。(你可以为项目中添加一个“全局应用程序类”即Global.asax.cs,可以看到在文件中列出了许多pipeline中的事件可供重写)

Pipeline

1. Validate the request

2. Perform URL mapping

3. Raise the BeginRequest event

...

15. Call the
ProcessRequest method of the appropriate
IHTTPHandler class for the request

24. Raise the EndRequest event

25. Raise the PreSendRequestHeaders event

26. Raise the PreSendRequestContent event

经过pipeline后,response就发给了client,一次请求的生命周期就结束了。特别注意15:在这一步将为特定的request实例化一个能够处理它的HTTPHandler实例,并invoke它实现的ProcessRequest接口。如请求的是web page,则将根据扩展名(.aspx)来实例化一个对应的IHTTPHandler类,也就是在这个时候,我们通常这样写的类:

public partial class MyWebForm : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}

MyWebForm就会被构造,继而开始Web Page Life Cycle。对!你理解的没错儿,ProcessRequest正是代表了Web Page的生命周期。

那HTTPModule和HTTPHandler到底是怎么用呢?

实际上pinepline是由HTTPModule和HTTPHandler组成的,可以简单看成是这样:



是的,你甚至可以创建一个可以处理请求后缀为自定义扩展名(如.asi)的HTTPHandler。就是说,当你的请求后缀为.asi,ASP.NET将实例化你自己的HTTPHanlder来处理,是不是很6?

当然了,还可以通过在HTTPModule上”做手脚”来对所有请求都进行一致的处理。比如在BeginRequest、EndRequest事件加一句提示,这样不论对于.aspx或.asi都会生效。

现在来看看具体怎么实现。

三、My custom HTTPModule and HTTPHandler

找到工程根目录下名为App_Code的文件夹,若无则手动创建一个。该文件夹中的source file将在运行时编译并缓存。

(1) HTTPModule

实现需要两步:1. 实现IHTTPModule接口;2. Register your custom HTTPModule

在App_Code文件夹中新增一个.cs文件,命名为HelloWorldHTTPModule.cs。自定义的HTTPModule必须实现IHTTPModule接口,在Init中register自己的event handler。

1. 实现接口

我们在BeginRequest和EndRequest事件上增加了我们自己的事件,输出一段文字。

public class HelloWorldModule : IHttpModule
{
public string ModuleName
{
get { return "HelloWorldModule"; }
}

//Use the Init method to register event handling methods with specific events
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(Application_BeginRequest);
application.EndRequest += new EventHandler(Application_EndRequest);
}

public void Dispose()
{

}

private void Application_BeginRequest(Object o, EventArgs e)
{
HttpApplication application = (HttpApplication)o;
HttpContext context = application.Context;
string filePath = context.Request.FilePath;
string fileExtension = VirtualPathUtility.GetExtension(filePath);

if (fileExtension.Equals(".aspx"))//只为.aspx请求处理,若要对所有requests处理,请去掉if这个判断。
{
context.Response.Write("<h1><font color=red>" +
"HelloWorldModule: Beginning of Request" +
"</font></h1><hr>");
}
}

private void Application_EndRequest(Object o, EventArgs e)
{
HttpApplication application = (HttpApplication)o;
HttpContext context = application.Context;
string filePath = context.Request.FilePath;
string fileExtension = VirtualPathUtility.GetExtension(filePath);

if (fileExtension.Equals(".aspx"))//同上
{
context.Response.Write("<h1><font color=red>" +
"HelloWorldModule: End of Request" +
"</font></h1><hr>");
}
}
}

2. Register my custom HTTPModule

在根目录下的Web.config文件中,在<modules> section中注册HelloWorldModule:

<configuration>
<system.webServer>
<modules>
<add name="AnyNameYouLike" type="HelloWorldModule"/>
</modules>
</system.webServer>
</configuration>

3. Test

保存文件(无需编译App_Code下的源文件)。重新打开web page,你会看到在页面上下都会标记有BeginRequest、EndRequest的信息。这是因为运行时编译了你的HTTPModule---HelloWorldModule,因此对于.aspx请求都会有这个信息。

(2) HTTPHandler

HTTPHandler实现的方式和上述一致。

1. 实现IHTTPHandler接口

我们想搞一个能够处理.asi请求的HTTPHandler!

同样,在App_Code文件夹中新建一个.cs文件,命名为HelloAsiHTTPHandler.cs。而后实现IHTTPHandler的两个接口。

namespace WebApplication6.App_Code
{
public class HelloAsiHandler : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
HttpResponse Response = context.Response;
Response.Write("<html>");
Response.Write("<body>");
Response.Write("<h1>Hello Asi from a synchronous custom HTTPAsiHandler.</h1>");
Response.Write("</body>");
Response.Write("</html>");
}

public bool IsReusable
{
get
{
return false;
}
}
}
}
2. Register my custom HTTPHandler

在根目录下的Web.config文件中,在<handlers> section中注册HelloWorldModule:

<configuration>
<system.webServer>
<handlers>
<add verb="*" path="*.asi" name="AnythingYouLike" type="WebApplication6.App_Code.HelloAsiHandler"/>
</handlers>
</system.webServer>
</configuration>

其中,verb表示HTTP类型,如GET、POST;path就是请求的URL,这里表示任何后缀为.asi的URL;type一定要写对,注意由于属于命名空间里的,因此要加上限定。

3. Test

保存运行,如当前网页URL为http://localhost:29233/WebForm1.aspx, 试试修改浏览器URL后缀为.asi。不要改了域名和端口!如http://localhost:29233/hisSixUncle.asi,欢快地击打Enter键,不出意外的话page将显示一个<h1>标题”Hello Asi from a synchronous custom HTTPAsiHandler.“。

四、总结

最近项目不忙,看了好多MSDN终于比以前小白只知道写却不知道为什么的时候强多了。写出一些心得体会分享一下,肯定有不妥之处,还望指正,希望没有误导你。。

记以供日后温习。

引用一句《程序员:从小工到专家》的话,”有的程序员根本不知道自己写的代码都做了些什么“。感觉这就是在说我[捂脸]。

五、References (能把这些多看几遍对提高ASP.NET的大局观很有帮助, especially 1 & 2)

1. ASP.NET Application Life Cycle Overview for IIS 7.0

2.
Understanding ASP.NET View State

3.
HTTP Handlers and HTTP Modules Overview

4.
Walkthrough: Creating and Registering a Custom HTTP Module

5.
Walkthrough: Creating a Synchronous HTTP Handler


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息