首先新建一个一般处理程序(.ashx ),因为一般处理程序是没有经过任何微软封装的处理程序,可以比较明晰的看到服务器对页面的整个解析处理过程,页面默认代码如下:
<%@ WebHandler Language="C#" class="Handler" %>
using System;
using System.Web;
public class Handler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}
public bool IsReusable {
get {
return false;
}
}
}
直接浏览该网页会在页面上输出Hello World,这一简单现象背后隐藏着什么不为人知的秘密呢?
浏览器通过网络访问服务器,由服务器软件接收到请求,服务器软件发现处理不了这种后缀名的文件,就通过映射表将请求转给了服务器扩展程序中的一个叫做ASPNET_ISAPI.DLL 的程序,可扩展程序又交给网站程序。
当一个页面请求过来的时候,网站程序中的HttpRuntime会启动, 由这个类开始处理所有的请求,这个类做了哪些事情呢,通过反编译工具来一看便知
从ProcessRequest方法进去
当请求过来的时候由HttpRunTime创建一个上下文对象(HttpContext)和一个Application对象
HttpContext里面两个及其重要的属性HttpRequest、HttpResponse同时被创建,并且也已经封装了数据
Request中的数据就是从请求报文来的,但是请求报文首先是给了HttpWorkRequest,然后在传入HttpRequest中
Response中主要包含了一个流(FileStream)用来保存页面类执行过程中要发送给浏览器的数据,它里面有一个缓存
那么这个Application是如何被创建的呢?Application与Context之间又是怎样的关系呢?继续往下看……
进入ProcessRequestNow(wr);开始processrequest方法的真正执行,继续点击进去主要是调用了ProcessRequestInternal(wr)
在上图的下部(未完全显示出来)还有一段极其重要的代码
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);//调用HttpApplicationFactory方法创建Application实例
if (applicationInstance == null)
{
throw new HttpException(SR.GetString("Unable_create_app_object"));
}
if (EtwTrace.IsTraceEnabled(5, 1))
{
EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, applicationInstance.GetType().FullName, "Start");
}
if (applicationInstance is IHttpAsyncHandler)
{
IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
context.AsyncAppHandler = handler2;
handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);
}
else
{
applicationInstance.ProcessRequest(context);//将上下问对象作为参数传给application对象
this.FinishRequest(context.WorkerRequest, context, null);
}
}
catch (Exception exception)
{
context.Response.InitResponseWriter();//上下文对象的Write方法
this.FinishRequest(wr, context, exception);
}
因为在Application中要运行被请求页面类(通过反射的方式创建页面类,然后将其转化成IHttpHander接口,调用里面的ProcessRequest方法来执行具体的代码)中的ProcessRequest方法,所以需要将HttpContext对象传入HttpApplication中来。
看到这里相信您对整个页面请求的过程有了一个比较深入的认知,最终全权负责处理请求的application怎样将生成的代码输出到客户端的呢,就是在 InitResponseWriter方法里
两点总结和一些注释
1.1分析请求报文,并将报文数据封装入一个叫做HttpWorkerRequest类对象中
1.2通过调用HttpApplicationFactory类的一个静态方法来创建HttpApplication对象。
因为服务器软件开发人员,在开发的时候不知道用户会访问具体哪个动态页面类,所以必须规定一个统一的调用标准。于是他们想到了,让部属在服务器上的每个动态页面都强制实现一个接口的方式,来统一了调用的标准。这样,当服务器软件接收到浏览器的动态页面请求时,只管根据你的请求文件通过反射的方式来创建被请求类的对象,然后将对象转成接口,通过统一调用接口方法,来执行页面类里具体的实现代码。