IHttpHandler接口
是否想学习HTTP处理程序编程呢?好吧,第一步工作是熟悉IHttpHandler接口。HTTP处理程序只不过是实现该接口的托管类。更确切地 讲,同步HTTP处理程序实现IHttpHandler接口;而异步HTTP处理程序实现IHttpAsyncHandler接口。让我们先看看同步处理 程序。
IHttpHandler接口的合同定义了HTTP处理程序以同步方式处理一个HTTP请求需要采取的行动。
1. IHttpHandler接口的成员
IHttpHandler接口只定义了两个成员:ProcessRequest和IsReusable,如表2.1所示。ProcessRequest是一个方法,而IsReusable是一个布尔逻辑属性。
表2.1 IHttpHandler接口的成员
成 员 |
描 述 |
IsReusable |
该属性获得一个布尔值,指示另一个请求是否可以使用该HTTP处理程序的实例 |
ProcessRequest |
该方法处理HTTP请求 |
Page类上的IsReusable属性返回false,表示需要该HTTP请求的新实例来服务一个页面请求。通常我们使它在所有情况下都返回 false,并根据请求负荷的不同而要求它做一些有意义的处理。那些被用作筛选特殊请求的简单屏障的处理程序可以将IsReusable设置为true, 以节省一些CPU周期。稍后我将用一个具体的实例来说明这一点。
ProcessRequest方法具有如下签名:
void ProcessRequest(HttpContext context);
它以请求的上下文作为输入,并确保该请求得到服务。在同步处理程序的情况下,当ProcessRequest返回时,准备把输出发到客户端。
2. 一个简单的HTTP处理程序
再次强调,HTTP处理程序只是一个实现了IHttpHandler接口的类。请求的输出是在ProcessRequest方法中建立的,如下面的代码所示:
using System.Web;
namespace ProAspNet20.Advanced.CS.Components
{
public class SimpleHandler : IHttpHandler
{
// Override the ProcessRequest method
public void ProcessRequest(HttpContext context)
{
context.Response.Write("<H1>Hello, I'm an HTTP handler</H1>");
}
// Override the IsReusable property
public bool IsReusable
{
get { return true; }
}
}
}
我们需要一个能够调用该处理程序的入口点。在此上下文中,该处理程序代码的入口点只不过是一个HTTP终点——即,一个公共的URL。该URL必须 有一个惟一的名称,使IIS和ASP.NET运行库能够把它映射到该代码。注册时,HTTP处理程序和Web服务器资源之间的映射是通过 web.config文件建立的。
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="myHandler.aspx"
type="ProAspNet20.Advanced.CS.Components.SimpleHandler" />
</httpHandlers>
</system.web>
</configuration>
<httpHandlers>节列出了当前应用程序可用的处理程序。这些设置指示,对myHandler.aspx终点的任何输入请 求,由SimpleHandler处理程序负责处理。要注意的是,myHandler.aspx URL不必是服务器上的物理资源;它只是一个公共资源标识符。type属性引用包含该处理程序的类和程序集,它的标准格式是 type[,assemly]。如果该组件在App_Code或其他保留文件夹中定义,则忽略该程序集信息。
注意 如果在machine.config文件中输入上述设置,则将把SimpleHandler组件注册成可以从服务器机器上托管的所有Web应用程序内可调用的组件。
如果调用myHandler.aspx URL,将得到如图2.2所示的结果。
图2.2 一个响应myHandler.aspx请求的HTTP处理程序示例
这里所述的方法是使用HTTP处理程序最快、最简单的方法,但是有关HTTP处理程序注册的知识,我们还有很多要了解并且还有很多其他选项可以利用。现在,让我们考虑一个更复杂的HTTP处理程序示例。
HTTP处理程序与ASP.NET页面
我们应当利用HTTP处理程序资源来实现应用程序特有的功能,它们需要比常规的Web页面被更快地处理。在任何情况 下,HTTP处理程序返回一个带有内容类型和主体的有效的HTTP响应。服务一个.ashx请求,或者一个自定义处理程序托管的任何其他请求,可能会导致 比服务一个.aspx资源更快的代码。ASP.NET处理一个自定义的处理程序通常更快,因为这不必对用户代码引发任何中间事件(例如,Init, Load),不必托管任何视图状态,而且也不支持任何回发机制。大概说来,对一个自定义的HTTP处理程序的请求类似于对.aspx资源的请求,其中只发 生呈现步骤。此外,找到服务一个页面请求所需的正确的HTTP处理程序可能需要更长的时间,因为这要牵涉到一个页面处理程序工厂的中间对象。
这就是说,我们要记住,ASP.NET页面只是一个HTTP处理程序——虽然是一个非常复杂而高级的HTTP处理程序。底层 的处理机制完全相同。如果说满足某种特定需要的自定义的HTTP处理程序通常比页面更快,这是因为它们通常是为了直接得到给定结果而实现的。例如,假设我 们需要显示从一个数据库中取出来的一个图像——这是我们将在第9章中详细讨论的一个主题,我们仍然需要将一个Image控件绑定到一个服务合适的MIME 类型的URL。该URL应当是一个页面吗?它当然可以是页面;但是,如果使用一个自定义的HTTP处理程序,通常会处理得更快。
ASP.NET页面是一个复杂对象,并由一个自定义的而且必定是复杂的HTTP处理程序(Page类)提供服务。就服务自定义资源而言,一定要使用一个合适的处理程序,只包
含必需的智能和复杂度。为了说明这一点,假设要运行一个查询并提供一个数据库中存储的一个图像的字节,我们不需要任何视图状态和回发管理,也不需要向该应用程序激发事件。
应当使用一般的.ashx资源,还是使用一个自定义的扩展呢?这主要取决于需要实现的功能。ASHX方法是为相对简单的场景 设计的,其中几乎不需要传递什么参数(或者根本不需要参数),并使用查询字符串来引入它们。如果有一个自定义的文档要处理,并且该文档具有以非平面的或复 杂的布局进行组织的各种信息,则最好使用自定义的扩展。