• 用反编译工具透析.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对象。

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

  • 相关阅读:
    Linux目录图解
    Linux-Monitor-Tools
    常用系统及工具下载
    vim 编辑器常规使用
    Win10 安装.NET framework 3.5
    Apache 2.4.6 新增虚拟目录
    html5
    CentOS 7 修改ssh端口
    CentOS7 设置密码复杂度
    CentOS 7安装 hping
  • 原文地址:https://www.cnblogs.com/luseike/p/2709777.html
Copyright © 2020-2023  润新知