Writing A Page To A String

ASP.NET Pages are designed to stream their output directly to a response stream. This can be a huge performance benefit for large pages as it doesn’t require buffering and allocating very large strings before rendering. Allocating large strings can put them on the Large Object Heap which means they’ll be sticking around for a while.

string However, there are many cases in which you really want to render a page to a string so you can perform some post processing. I wrote about one means using a Response filter eons ago.

However, recently, I learned about a method of the Page class I never noticed which allows me to use a much lighter weight approach to this problem.

The method in question is CreateHtmlTextWriter which is protected, but also virtual.

So here’s an example of the code-behind for a page that can leverage this method to filter the output before its sent to the browser.

public partial class FilterDemo : System.Web.UI.Page
{
  HtmlTextWriter _oldWriter = null;
  StringWriter _stringWriter = new StringWriter();

  protected override HtmlTextWriter CreateHtmlTextWriter(TextWriter tw)
  {
    _oldWriter = base.CreateHtmlTextWriter(tw);
    return base.CreateHtmlTextWriter(_stringWriter);
  }

  protected override void Render(HtmlTextWriter writer)
  {
    base.Render(writer);
    string html = _stringWriter.ToString();
    html = html.Replace("REPLACE ME!", "IT WAS REPLACED!");
    _oldWriter.Write(html);
  }
}

In the CreateHtmlTextWriter method, we simply use the original logic to create the HtmlTextWriter and store it away in an instance variable.

Then we use the same logic to create a new HtmlTextWriter, but this one has our own StringWriter as the underlying TextWriter. The HtmlTextWriter passed into the Render method is the one we created. We call Render on that and grab the output from the StringWriter and now can do all the replacements we want. We finally write the final output to the original HtmlTextWriter which is hooked up to the response.

A lot of caveats apply in using this technique. First, as I mentioned before, for large pages, you could be killing scalability and performance by doing this. Also, I haven’t tested this with output caching, async pages, etc… etc…, so your mileage may vary.

Note, if you want to call one page from another, and get the output as a string within the first page, you can pass your own TextWriter to Server.Execute, so this technique is not necessary in that case.

Tags:

What others have said

Requesting Gravatar... Gene May 29, 2009 10:26 AM
# re: Writing A Page To A String
With regard to asp.net streaming a page, Steve Souders (YSlow) mentions using www.stevesouders.com/.../flushing-the-document-...

(stackoverflow suggests Response.Flush() stackoverflow.com/.../can-i-flush-the-buffer-ea... )

to start the browser downloading other files rather than waiting for the html doc to finish downloading.

How/Does this work with MVC?
Requesting Gravatar... Morten Lyhr May 29, 2009 12:09 PM
# re: Writing A Page To A String
How can I do this in MVC?

I would really like to use MVC as a template engine to create email, xml content to be stored on the servers disk etc.
Requesting Gravatar... Victor Kornov May 29, 2009 12:19 PM
# re: Writing A Page To A String
Doesn't need any CreateHtmlTextWriter:
protected override void Render(HtmlTextWriter writer)
{
var sw = new StringWriter();
var w = new HtmlTextWriter(sw);

base.Render(w);

string html = sw.ToString();
html = html.Replace("REPLACE ME!", "IT WAS REPLACED!");

writer.Write(html);
}
Requesting Gravatar... Andrew Peters May 29, 2009 12:22 PM
# re: Writing A Page To A String
@Morten

One way is like this: andrewpeters.net/.../in-process-aspnet-mvc-web-...
Requesting Gravatar... neonp May 29, 2009 2:22 PM
# re: Writing A Page To A String
Hello,

Maybe did I missed something, but why not using an HttpModule to solve this problem ? you could filter the response easily. You won't have this problem of string huge size. Correct me if I'm wrong.
Requesting Gravatar... Haacked May 29, 2009 3:51 PM
# re: Writing A Page To A String
@neonp the point of this is that it hints at a means of rendering an ASP.NET MVC view to a string, a common request.
Requesting Gravatar... guoyz May 29, 2009 9:17 PM
# re: Writing A Page To A String
what's meaning?

can you translate it to chinese?
Requesting Gravatar... Chris Charabaruk May 29, 2009 9:19 PM
# re: Writing A Page To A String
Off the tope of your head, do you know if it'd be possible to use this to generate page output that'll never be sent to a user's browser (say, so you can use views to build e-mails to send to users instead)?
Requesting Gravatar... Haacked May 29, 2009 10:44 PM
# re: Writing A Page To A String
@Chris yes, exactly. You don't have to send the output to the response using this approach if you don't want to.
Requesting Gravatar... Paul St. Amant, softomic.com May 30, 2009 12:54 AM
# re: Writing A Page To A String
Interesting idea. Maybe you could even store a whole website in a single blob and just parse it with a single function. A whole book can be a single pdf file, why not a whole site? Maybe not practical, but an interesting concept.
Requesting Gravatar... Jon May 31, 2009 1:34 AM
# re: Writing A Page To A String
I recently required the need to return the output from a Partial view to put in a JSON object. I found this and just wondered if this was a better approach?
Requesting Gravatar... jinrutan Jun 04, 2009 2:23 AM
# re: Writing A Page To A String
That's great idea,so helpful!
I still using response filter,but i think using the solution will be great!

What do you have to say?

(will show your gravatar)
Please add 3 and 4 and type the answer here: