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);

  }

  }