zoukankan      html  css  js  c++  java
  • 窥探:属性HttpResponse.Filter和方法 HttpResponse.SwitchWriter

      wap站由于浏览器的原因,只能依赖url来做用户标识了,如此我们就必须对输出页面中的url做处理了。就是说要截住response的内容,然后对其进行处理。

      

      首先来看段源码:

        internal TextWriter SwitchWriter(TextWriter writer)
        {
            TextWriter writer2 
    = this._writer;
            
    this._writer = writer;
            
    return writer2;
        }

      原来的代码里用此方法来替换HttpResponse的输出对象。留意了,是替换,把原有的替换了。接下来看看原有的writer是什么东东。

      

      

        internal void InitResponseWriter()
        {
            
    if (this._httpWriter == null)
            {
                
    this._httpWriter = new HttpWriter(this);
                
    this._writer = this._httpWriter;
            }
        }

    默认情况writer的东东都写到httpwriter里面去了。

    HttpResponse.Writer:

        public void Write(char ch)
        {
            
    this._writer.Write(ch);
        }

    注:SwitchWriter的方法返回的是老的response._writer的对象,如果咱们在输出前通过SwithchiWriter获取默认的_htppWriter对象来进行处理的话,我们得到的只能是空串,原因是httpWriter对象默认直接将流输出到客户端了。

    所以原来的代码调用了2次SwitchWriter,在OnActionExecuting中把默认的_htppWriter用HtmlTextWriter的实例替换掉,待action执行完成,再在OnResultExecuted中再一次调用SwitchWriter将先前替换进去的对象取出来。(不明白,再看看SwitchWriter的定义)。

    SwitchWriter方法是internal的,我们只能靠反射干它了。

    哈哈,其实现在的实现也挺好。问题出现在有bug的时候,什么叫有bug的时候就有问题,岂不是废话,有bug当然有问题了,呵,别着急,慢慢来。

    在MVC中,如果咱们自己写的Action代码出现了异常,其是不会走OnResultExecuted事件的,直接跳转到OnException 里去处理了,也就是要想把Resopnse 对应的输出去出来,让程序员看到“黄页”那还得在OnException里去进行一次SwitchWriter来取错误信息。也罢也罢。关键也不知道写着代码的人知道其中逻辑,目前OnException只做了跳转,“黄页”永远都告别了程序员和用户。“黄页”对debug来说有多重要就不说了。

      因为这个问题,我们不得不想起HttpResponse.Filter。

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

    看到这里应该知道为啥人家把SwitchWriter方法给internal起来了。

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

    算看出来了,filter的功能是HttpWriter 提供的filter方法实现的:

        internal void Filter(bool finalFiltering)
        {
            
    if (this._installedFilter != null)
            {
                
    if (this._charBufferLength != this._charBufferFree)
                {
                    
    this.FlushCharBuffer(true);
                }
                
    this._lastBuffer = null;
                
    if (this._buffers.Count != 0)
                {
                    ArrayList list 
    = this._buffers;
                    
    this._buffers = new ArrayList();
                    
    this._filterSink.Filtering = true;
                    
    try
                    {
                        
    int count = list.Count;
                        
    for (int i = 0; i < count; i++)
                        {
                            IHttpResponseElement element 
    = (IHttpResponseElement) list[i];
                            
    long size = element.GetSize();
                            
    if (size > 0L)
                            {
                                
    this._installedFilter.Write(element.GetBytes(), 0, Convert.ToInt32(size));
                            }
                        }
                        
    this._installedFilter.Flush();
                    }
                    
    finally
                    {
                        
    try
                        {
                            
    if (finalFiltering)
                            {
                                
    this._installedFilter.Close();
                            }
                        }
                        
    finally
                        {
                            
    this._filterSink.Filtering = false;
                        }
                    }
                }
            }
        }

      filter在输出前做过滤筛选,方便。

      有一个不太好的地方是,MS公布出来个Stream类型的filter,很不让人好理解。强烈要求放出个delegate,意思明了多了。

     想起来了,之前在action里面用 Response.End();返回的却是空的页面。

    那就再偷窥下end方法。我们在actionexcuting中用SwithWrite方法把 默认的httpwriter换成了TextWriter的实例,我们来看看End方法。

        public void End()
        {
            
    if (this._context.IsInCancellablePeriod)
            {
                InternalSecurityPermissions.ControlThread.Assert();
                Thread.CurrentThread.Abort(
    new HttpApplication.CancelModuleException(false));
            }
            
    else if (!this._flushing)
            {
                
    this.Flush();
                
    this._ended = true;
                
    if (this._context.ApplicationInstance != null)
                {
                    
    this._context.ApplicationInstance.CompleteRequest();
                }
            }
        }

    我们发现,我们得跟Flush()方法。

        public void Flush()
        {
            
    if (this._completed)
            {
                
    throw new HttpException(SR.GetString("Cannot_flush_completed_response"));
            }
            
    this.Flush(false);
        }

        
    private void Flush(bool finalFlush)
        {
            
    if (!this._completed && !this._flushing)
            {
                
    if (this._httpWriter == null)
                {
                    
    this._writer.Flush();
                }
                
    else
                {
                    
    this._flushing = true;
                    
    try
                    {
                        IIS7WorkerRequest request 
    = this._wr as IIS7WorkerRequest;
                        
    if (request != null)
                        {
                            
    this.GenerateResponseHeadersForHandler();
                            
    this.UpdateNativeResponse(true);
                            request.ExplicitFlush();
                            
    this._headersWritten = true;
                        }
                        
    else
                        {
                            
    long contentLength = 0L;
                            
    if (!this._headersWritten)
                            {
                                
    if (!this._suppressHeaders && !this._clientDisconnected)
                                {
                                    
    if (finalFlush)
                                    {
                                        contentLength 
    = this._httpWriter.GetBufferedLength();
                                        
    if ((!this._contentLengthSet && (contentLength == 0L)) && (this._httpWriter != null))
                                        {
                                            
    this._contentType = null;
                                        }
                                        
    if (((this._cachePolicy != null&& (this._cookies != null)) && (this._cookies.Count != 0))
                                        {
                                            
    this._cachePolicy.SetHasSetCookieHeader();
                                            
    this.DisableKernelCache();
                                        }
                                        
    this.WriteHeaders();
                                        contentLength 
    = this._httpWriter.GetBufferedLength();
                                        
    if (!this._contentLengthSet && (this._statusCode != 0x130))
                                        {
                                            
    this._wr.SendCalculatedContentLength(contentLength);
                                        }
                                    }
                                    
    else
                                    {
                                        
    if ((!this._contentLengthSet && !this._transferEncodingSet) && (this._statusCode == 200))
                                        {
                                            
    string httpVersion = this._wr.GetHttpVersion();
                                            
    if ((httpVersion != null&& httpVersion.Equals("HTTP/1.1"))
                                            {
                                                
    this.AppendHeader(new HttpResponseHeader(6"chunked"));
                                                
    this._chunked = true;
                                            }
                                            contentLength 
    = this._httpWriter.GetBufferedLength();
                                        }
                                        
    this.WriteHeaders();
                                    }
                                }
                                
    this._headersWritten = true;
                            }
                            
    else
                            {
                                contentLength 
    = this._httpWriter.GetBufferedLength();
                            }
                            
    if (!this._filteringCompleted)
                            {
                                
    this._httpWriter.Filter(false);
                                contentLength 
    = this._httpWriter.GetBufferedLength();
                            }
                            
    if ((!this._suppressContentSet && (this.Request != null)) && (this.Request.HttpVerb == HttpVerb.HEAD))
                            {
                                
    this._suppressContent = true;
                            }
                            
    if (this._suppressContent || this._ended)
                            {
                                
    this._httpWriter.ClearBuffers();
                                contentLength 
    = 0L;
                            }
                            
    if (!this._clientDisconnected)
                            {
                                
    if ((this._context != null&& (this._context.ApplicationInstance != null))
                                {
                                    
    this._context.ApplicationInstance.RaiseOnPreSendRequestContent();
                                }
                                
    if (this._chunked)
                                {
                                    
    if (contentLength > 0L)
                                    {
                                        
    byte[] bytes = Encoding.ASCII.GetBytes(Convert.ToString(contentLength, 0x10+ "\r\n");
                                        
    this._wr.SendResponseFromMemory(bytes, bytes.Length);
                                        
    this._httpWriter.Send(this._wr);
                                        
    this._wr.SendResponseFromMemory(s_chunkSuffix, s_chunkSuffix.Length);
                                    }
                                    
    if (finalFlush)
                                    {
                                        
    this._wr.SendResponseFromMemory(s_chunkEnd, s_chunkEnd.Length);
                                    }
                                }
                                
    else
                                {
                                    
    this._httpWriter.Send(this._wr);
                                }
                                
    this._wr.FlushResponse(finalFlush);
                                
    this._wr.UpdateResponseCounters(finalFlush, (int) contentLength);
                                
    if (!finalFlush)
                                {
                                    
    this._httpWriter.ClearBuffers();
                                }
                            }
                        }
                    }
                    
    finally
                    {
                        
    this._flushing = false;
                        
    if (finalFlush)
                        {
                            
    this._completed = true;
                        }
                    }
                }
            }
        }

     这才发现,这个end 依赖于_writer的法律flush方法,而TextWrter的实现是:

    [MethodImpl(MethodImplOptions.Synchronized)]
    public override void Flush()
    {
        
    this._out.Flush();
    }

     

    所以,默认情况下end方法依赖于默认的httpwriter的flush实现,或者自己重写textwriter的flush方法。

  • 相关阅读:
    第二次结对编程作业
    团队项目-需求分析报告
    团队项目-选题报告
    第一次结对编程作业
    第一次个人编程作业
    第一次博客作业
    第04组 团队Git现场编程实战
    第二次结对编程作业
    团队项目-需求分析报告
    团队项目-选题报告
  • 原文地址:https://www.cnblogs.com/buaaboyi/p/2144820.html
Copyright © 2011-2022 走看看