views:

545

answers:

3

Hi all,

I've created a simple HttpModule and response stream to reformat the rendered output of web pages (see code snippets below).

In the HttpModule I set the Response.Filter to my PageStream:

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

In the PageStream I overwrite the Write method in order to do my reformatting of the rendered output:

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

And this work fine when using it on simple HTML pages (.html), but when I use this method on ASPX pages (.aspx), the Write method is called several times, splitting up the reformatting into different steps, and potentially destroying the string replacement operations.

How do I solve this? Is there a way to let the ASPX page NOT call Write several times, e.g. by changing its buffer size, or have I chosen the wrong approach entirely, by using this Response.Filter method to manipulate the rendered output?

+1  A: 

You might need to check the content type before attaching the response filter:

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

There's also a nice article describing response filters in ASP.NET.

Darin Dimitrov
Although your answer didn't make any sense in relation to my question, I naturally check for the content type before setting the Response.Filter, the supplied article did help me out. Thanks.
PropellerHead
+1  A: 

I would just buffer the data in the Write method, and do the string operations in the Close method, like this:

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

(Maybe even better if you collect the data in a MemoryStream)

Gabor Szokoly
A: 

Guided by the article suggested by Darin Dimitrov, I ended with the following implementation of the Write method that also works perfectly with ASPX pages:

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

The code leverages a StringBuilder (m_ResponseHtml) to accumulate the entire HTML, before doing the actual string manupulation on the rendered output.

PropellerHead