andrewlocatelliwoodcock

Thoughts on Software

Capturing the output of a View as a String

with 3 comments


There are times when it is very useful to be able to capture the output of a View as a string, perhaps to log it or, in a  case I recently encountered, in order to convert that HTML to PDF using an HTML-to-PDF conversion tool. So, for whatever reason, you need to capture the string output.

Once again, MVC makes this relatively straightforward even when using the Web Forms engine.

The basic task we have to accomplish is to swap the existing HttpContext object (which contains the HtmlTextWriter that is outputting to the response stream) for one which contains an HtmlTextWriter we control and which is outputting to a StringBuilder object instead, call the View’s ExecuteResult method and then swap it all back again afterwards …

Although straightforward in concept, this is slightly involved in practice, probably more so than it needs to be.

The best way to explain is doubtless with some well-commented sample code, so here goes …

public string CaptureViewOutput(Controller controller, ViewResult view)
{
    var builder = new StringBuilder();
    using (var stringWriter = new StringWriter(builder))
    {
        using (var htmlTextWriter = new HtmlTextWriter(stringWriter))
        {
            var currentContext = controller.ControllerContext.HttpContext;

            try
            {
                // get the Request and User objects from the current, unchanged context
                var currentRequest = HttpContext.Current.ApplicationInstance.Context.Request;
                var currentUser = HttpContext.Current.ApplicationInstance.Context.User;

                // create our new HttpResponse object containing our HtmlTextWriter
                var newResponse = new HttpResponse(htmlTextWriter);

                // create a new HttpContext object using our new Response object and the existing Request and User objects
                var newContext = new HttpContextWrapper(
                            new HttpContext(currentRequest, newResponse)
                            {
                                User = currentUser
                            });

                // swap in our new HttpContext object - output from this controller is now going to our HtmlTextWriter object
                controller.ControllerContext.HttpContext = newContext;

                // Run the ViewResult
                view.ExecuteResult(controller.ControllerContext);

                // flush the output
                newResponse.Flush();
                htmlTextWriter.Flush();
                stringWriter.Flush();

            }
            finally
            {
                // and no matter what happens, set the context back!
                controller.ControllerContext.HttpContext = currentContext;
            }
        }
    }

    // our StringBuilder object now contains the output of the ViewResult object
    return builder.ToString();

}

Written by andrewlocatelliwoodcock

April 28, 2011 at 20:05

Posted in ASP.Net MVC

Tagged with , , ,

3 Responses

Subscribe to comments with RSS.

  1. Wonderful goods from you, man. I have understand your stuff previous to and you’re just too great. I really like what you have acquired here, really like what you’re stating and the way in which you say it. You make it enjoyable and you still care for to keep it wise. I can’t wait to read far more from you. This is really a terrific web site.

    Ellie Hounchell

    August 10, 2011 at 16:08

  2. Thank you, this was just what I needed. Because of IE problems in CORS requests, I needed a wrapper around the output, so I used the basics of your code, creating an ActionFilterAttribute that divided the function between OnResultExecuting and OnResultExecuted.

    Andreas

    June 26, 2013 at 13:12

    • Glad it helped Andreas! Sorry for the slow supply but there’s a mountain of spam comments to wade through …

      andrewlocatelliwoodcock

      November 14, 2013 at 11:07


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: