zoukankan      html  css  js  c++  java
  • HttpResponse的Output与OutputStream、Filter关系与区别

    在网上经常看见有这样的代码

      HttpResponse response = HttpContext.Current.Response;
                    response.Filter = new PageFilter(response.Filter);

    来拦截输出流,自己也做个类似的东东,如asp.net中 js 合并 压缩,现在我也来说说这几个东东是什么吧,需要大家对asp.net的生命周期比较熟悉,如不熟悉的朋友建议先看看ASP.NET 请求处理流程  ASP.NET管线与应用程序生命周期

    首先我们来看看这3个属性的源代码吧:

    public TextWriter Output
    {
        get
        {
            return this._writer;
        }
        set
        {
            this._writer = value;
        }
    }
    
    
    public Stream OutputStream
    {
        get
        {
            if (!this.UsingHttpWriter)
            {
                throw new HttpException(SR.GetString("OutputStream_NotAvail"));
            }
            return this._httpWriter.OutputStream;
        }
    }
    
    
    public Stream Filter
    {
         get
          {
              if (this.UsingHttpWriter)
              {
                  return this._httpWriter.GetCurrentFilter();
              }
              return null;
          }
          set
          {
              if (!this.UsingHttpWriter)
              {
                 throw new HttpException(SR.GetString("Filtering_not_allowed"));
              }
              this._httpWriter.InstallFilter(value);
              IIS7WorkerRequest request = this._wr as IIS7WorkerRequest;
              if (request != null)
              {
                 request.ResponseFilterInstalled();
              }
          }
     }

    我们看到Filter和OutputStream都用到了一个属性UsingHttpWriter,那这个属性是怎么定义的了

    private bool UsingHttpWriter
    {
     get
     {
      return ((this._httpWriter != null) && (this._writer == this._httpWriter));
      }
    }
    

      从这个属性我们可以知道_writer 、_httpWriter实际上是同一个东东,它们的类型是HttpWriter ,而HttpWriter 又继承与TextWriter。现在我们可以解释Output就是_httpWriter,而OutputStream是_httpWriter的OutputStream属性。类HttpWriter 主要代码如下

    public Stream OutputStream
    {
        get
        {
            return this._stream;
        }
    }
    
    
    internal HttpWriter(HttpResponse response) : base(null)
    {
        this._response = response;
        this._stream = new HttpResponseStream(this);
        this._buffers = new ArrayList();
        this._lastBuffer = null;
        this._charBuffer = (char[]) s_Allocator.GetBuffer();
        this._charBufferLength = this._charBuffer.Length;
        this._charBufferFree = this._charBufferLength;
        this.UpdateResponseBuffering();
    }
    
    
    internal HttpResponseStream(HttpWriter writer)
    {
        this._writer = writer;
    }

    HttpResponse 在Filter属性设置调用了HttpWriter类的InstallFilter方法,而获取调用了该类的GetCurrentFilter

    internal void InstallFilter(Stream filter)
    {
        if (this._filterSink == null)
        {
            throw new HttpException(SR.GetString("Invalid_response_filter"));
        }
        this._installedFilter = filter;
    }
    
    internal Stream GetCurrentFilter()
     {
         if (this._installedFilter != null)
         {
             return this._installedFilter;
         }
         if (this._filterSink == null)
         {
            this._filterSink = new HttpResponseStreamFilterSink(this);
         }
       return this._filterSink;
    }
    

      由以上代码我们可以得知HttpResponse的输出流就是Filter属性设置的流,即HttpResponse的Output和OutputStream属性的输出流都是来自Filter中的流。我们来看看_writer 、_httpWriter它们是在什么时候初始化的了?在HttpResonse中有一个方法
    internal void InitResponseWriter()
    {
        if (this._httpWriter == null)
        {
            this._httpWriter = new HttpWriter(this);
            this._writer = this._httpWriter;

        }
    }

    该方法是由HttpRuntime的ProcessRequestInternal来调用

    private void ProcessRequestInternal(HttpWorkerRequest wr)
    {
        HttpContext context;
        try
        {
            context = new HttpContext(wr, false);
        }
        catch
        {
            wr.SendStatus(400, "Bad Request");
            wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");
            byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
            wr.SendResponseFromMemory(bytes, bytes.Length);
            wr.FlushResponse(true);
            wr.EndOfRequest();
            return;
        }
        wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);
        Interlocked.Increment(ref this._activeRequestCount);
        HostingEnvironment.IncrementBusyCount();
        try
        {
            try
            {
                this.EnsureFirstRequestInit(context);
            }
            catch
            {
                if (!context.Request.IsDebuggingRequest)
                {
                    throw;
                }
            }
            context.Response.InitResponseWriter();
            IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);
            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);
                this.FinishRequest(context.WorkerRequest, context, null);
            }
        }
        catch (Exception exception)
        {
            context.Response.InitResponseWriter();
            this.FinishRequest(wr, context, exception);
        }
    }
    

      

     

  • 相关阅读:
    <转>Npoi导入导出Excel操作<载>
    将DataTable导出为Excel C#
    错误 X “X1”不包含“XX2”的定义,并且找不到可接受类型为“X1”的第一个参数的扩展方法“XX2”(是否缺少 using 指令或程序集引用?)
    错误 1 未知的服务器标记“asp:ScriptManager”。
    分析器错误消息: 类型“test.test.testx”不明确: 它可能来自程序集“F: estProjectin est.test.DLL”或程序集“F: estProjectin estProject.DLL”。请在类型名称中显式指定程序集。
    There are no interfaces on which a capture can be done.
    基础知识系列☞GET和POST→及相关知识
    基础知识系列☞Abstract和Virtual→及相关知识
    同源策略
    26Mybatis_一级缓存及其测试
  • 原文地址:https://www.cnblogs.com/majiang/p/2757706.html
Copyright © 2011-2022 走看看