回复:从底层了解ASP.NET体系结构
HttpHandlers
模块是相当低层次的,它针对每一个传入ASP.NET程序的请求触发。HTTP处理器则着重于处理一个指定的请求映射。通常一个页面扩展已经被映射到处理器了。
实现一个HTTP处理器所需要做的是非常基础的,但是通过访问HttpContext对象,就会有很多有用的功能。HTTP处理器通过一个简单IHttpHandler接口实现(或者它的异步版本IHttpAsyncHandler)。它仅仅有一个方法ProcessRequest()和一个属性IsReusable。这里的关键是ProcessRequest()会得到一个HttpContext对象的实例。这个单独的方法将从开始到结束负责处理一个Web请求。
单一的,简单的方法?可能太简单了,是吗?可是,一个简单的接口,但它的实现可能并不简单。记住,WebForms和WebServices都是作为HTTP处理器实现的。因此,在这个看似简单的接口里,过多的实现过程被隐藏了。关键是,事实上到现在,一个HTTP处理器可以访问所有为了开始处理请求而被组建和配置起来的ASP.NET的内置对象。关键是,HttpContext对象提供了所有与请求相关的功能,可以获取流入的数据和输出数据到Web服务器。
对于HTTP处理器而言,所有的操作都通过简单地调用ProcessRequest()方法执行。可以简单到如下的样子:
public void ProcessRequest(HttpContext context)
{
context.Response.Write("Hello World");
}
一个完整的实现像WebForms页面引擎那样,可以根据HTML模版展现复杂的表单。所以,这里的关键点是你想用这个简单但功能强大的接口做什么。
因为对你而言,HttpContext对象是可以使用的,这样你就可以访问Request,Response,Session和Cache对象,因此你已经拥有了ASP.NET请求的所有特征,可以自己做主如何处理用户提交的信息,然后给客户端返回处理后产生的内容。记住,在一个ASP.NET请求的生命期内,上下文对象始终都是你的朋友。
处理器的关键操作通常是往Response对象里写输出数据,或者更确切的说,是往Response对象的OutputStream里写。这个就是真正返回到客户端的输出数据。在底层,由ISAPIWorkerRequest负责把OutputStream发回给ISAPI的ecb.WriteClient方法,因为ecb.WriteClient方法才是真正执行IIS产生输出数据的。
通过使用大量的处于高层的、基础的框架接口,WebForms实现了一个HTTP处理器。但最后,WebForm的Render()方法却简单的使用了一个HtmlTextWriter对象,把最终的输出发送给context.Response.OutputStream对象而结束。因此,相当的奇妙,最终甚至一个高层次的工具像WebForm,也仅仅是在Response和Request对象之上的一个高层次的抽象。
在这个时候,你可能想知道,是否需要从头实现一个完整的HTTP处理器?毕竟WebForms已经提供了一个易用的HTTP处理器的实现,因此为什么还要为这些大量底层的东西而烦恼,放弃这些已经提供的灵活性呢?
WebForms是非常棒的,使用它可以生成复杂的HTML页面和处理业务层的逻辑而这些都需要图形化的设计和模版化的页面。除此以外,WebForms引擎还可以完成更多的,需要丰富的表现层的任务。如果所有你想做的是:从系统读取文件,由执行的代码把它返回。这样的任务,如果避开使用Web Forms页面框架,代替的是直接处理文件然后返回,相信后者才是更高效的方法。如果你做的事情仅仅是像从数据库里读取图片一样,那么完全没有必要使用页面框架来处理,因为这里的确没有Web UI需要你俘获离开图片的事件。
在这里找不到,组建一个页面对象和会话对象以及俘获页面层上事件的理由。对于你的任务而言,这里需要做的仅仅是执行代码,而这些与你手头上的任务毫不相干。
因此,这种情况下使用处理器会更加高效。处理器可以完成使用WebForms不可能完成的事情。比如:需要处理这样的请求,它们没有必要在磁盘上存在对应的物理文件,这些被请求的路径通常称为虚拟的URL。为了使这样的请求正常的工作,你需要确保已经在应用程序的扩展对话框(如图一所示)里关闭了“确认文件是否存在”的复选框。
对于内容提供者来说,这是通用的,如:动态的图像处理,XML服务,提供虚拟的URL使原来的URL重定向,下载管理等等,这些均不能使用WebForms实现。