用反编译工具透析.Net页面生成本质

首先新建一个一般处理程序(.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对象。

因为服务器软件开发人员,在开发的时候不知道用户会访问具体哪个动态页面类,所以必须规定一个统一的调用标准。于是他们想到了,让部属在服务器上的每个动态页面都强制实现一个接口的方式,来统一了调用的标准。这样,当服务器软件接收到浏览器的动态页面请求时,只管根据你的请求文件通过反射的方式来创建被请求类的对象,然后将对象转成接口,通过统一调用接口方法,来执行页面类里具体的实现代码。

原文地址:https://www.cnblogs.com/luseike/p/2709777.html