ASP.NET响应过滤器重新格式化ASPX页面的渲染输出?

时间:2009-10-10 08:14:28

标签: asp.net filter stream response httpmodule

我创建了一个简单的HttpModule和响应流来重新格式化网页的渲染输出(参见下面的代码片段)。

在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方法来操作渲染输出?

4 个答案:

答案 0 :(得分:2)

我只是在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中收集数据,可能会更好)

答案 1 :(得分: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。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

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

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