【问题标题】:ASP.NET Response Filter to Reformat the rendered output of ASPX pages?ASP.NET 响应过滤器重新格式化 ASPX 页面的呈现输出?
【发布时间】:2009-10-10 08:14:27
【问题描述】:

我创建了一个简单的 HttpModule 和响应流来重新格式化网页的呈现输出(参见下面的代码 sn-ps)。

在 HttpModule 中,我将 Response.Filter 设置为我的 PageStream:

m_Application.Context.Response.Filter = new PageStream(m_Application.Context);

在 PageStream 中,我覆盖了 Write 方法,以便重新格式化呈现的输出:

public override void Write(byte[] buffer, int offset, int count)
{
    string html = System.Text.Encoding.UTF8.GetString(buffer);
    //Do some string resplace operations here...
    byte[] input = System.Text.Encoding.UTF8.GetBytes(html);
    m_DefaultStream.Write(input, 0, input.Length);
}

在简单的 HTML 页面 (.html) 上使用它时效果很好,但是当我在 ASPX 页面 (.aspx) 上使用此方法时,Write 方法会被调用多次,将重新格式化分成不同的步骤,并且可能会破坏字符串替换操作。

我该如何解决这个问题?有没有办法让 ASPX 页面不调用 Write 多次,例如通过更改其缓冲区大小,还是我完全选择了错误的方法,通过使用此 Response.Filter 方法来操作呈现的输出?

【问题讨论】:

    标签: asp.net filter stream response httpmodule


    【解决方案1】:

    我会在 Write 方法中缓存数据,在 Close 方法中进行字符串操作,如下所示:

    private readonly Stream _forwardStream;
    private readonly StringBuilder _sb;
    
    // snip
    
    public override void Write (byte[] buffer, int offset, int count)
    {
      string chunk = Encoding.UTF8.GetString (buffer, offset, count);
      _sb.Append (chunk);
    }
    
    public override void Close ()
    {
      string result = GetManipulatedString ();
    
      byte[] rawResult = Encoding.UTF8.GetBytes (result);
      _forwardStream.Write (rawResult, 0, rawResult.Length);
    
      base.Close ();
      _forwardStream.Close ();
    }
    

    (如果您在 MemoryStream 中收集数据可能会更好)

    【讨论】:

      【解决方案2】:

      在 Darin Dimitrov 建议的文章的指导下,我完成了以下 Write 方法的实现,该方法也适用于 ASPX 页面:

      public override void Write(byte[] buffer, int offset, int count)
      {
          string strBuffer = System.Text.UTF8Encoding.UTF8.GetString (buffer, offset, count);
      
          if (!strBuffer.Contains("</html>"))
          {
              m_ResponseHtml.Append(strBuffer);
          }
          else
          {
              m_ResponseHtml.Append(strBuffer);
              string  html = m_ResponseHtml.ToString ();
      
              //Do some string operations here...
              byte[] input = System.Text.Encoding.UTF8.GetBytes(html);
              m_DefaultStream.Write(input, 0, input.Length);           
          }
      }
      

      代码利用 StringBuilder (m_ResponseHtml) 来累积整个 HTML,然后对呈现的输出进行实际的字符串操作。

      【讨论】:

        【解决方案3】:

        您可能需要在附加响应过滤器之前检查内容类型:

        var response = m_Application.Context.Response;
        if (response.ContentType == "text/html")
        {
            response.Filter = new PageStream(m_Application.Context);
        }
        

        还有一个很好的 article 描述 ASP.NET 中的响应过滤器。

        【讨论】:

        • 虽然您的回答对我的问题没有任何意义,但我自然会在设置 Response.Filter 之前检查内容类型,提供的文章确实帮助了我。谢谢。
        【解决方案4】:

        PropellerHead 的响应依赖于在最终缓冲区中找到结束的 html 标记,但实际上我的最终缓冲区太小而无法包含整个标记。

        一种更安全(也更有效)的方法是只在 Write 中进行追加,然后在 Close 中进行字符串操作和输出。

        【讨论】:

          猜你喜欢
          • 2018-03-21
          • 1970-01-01
          • 1970-01-01
          • 2012-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-04
          • 1970-01-01
          相关资源
          最近更新 更多