Filtering Razor Generated Output

 Introduction:

          There is no doubt that Razor view engine is becoming very popular because Razor is speeding things up just a little bit more. With Razor, sometimes it may be need to see the Razor generated HTML during debugging. Sometimes there's a need to filter, change or move the Razor generated HTML. Sometimes you may need to set the different properties of your view in a separate file(however I strongly recommended that you should make your view as simple as possible). Sometimes you may also need to log the Razor generated HTML. Sometimes you may need to emit some HTML in the response output at run time. In this article, I will show you how to can see and filter the Razor generated HTML using a simple way.

 

 Description:

          Razor views are inherited from WebViewPage class. WebViewPage class provides a ExecutePageHierarchy virtual method which we will override in our custom class. So create a new class file FilterRazorOutput.cs inside Helper folder and add the following code ,

 

    public class FilterRazorOutput : WebViewPage
    {
        public override void ExecutePageHierarchy()
        {
            PopContext();
            StringWriter writer = new StringWriter();
            PushContext(new WebPageContext(), writer);
            base.ExecutePageHierarchy();
            PopContext();
            Response.Clear();
            string output = writer.ToString();
            output = output.Replace("<body>", "<body><h1>An Example of Filtering Razor Output</h1>");
            Response.Write(output);
            Response.End();
        }

        public override void Execute()
        {
        }
    }

    public class FilterRazorOutput<T> : WebViewPage<T>
    {
        public override void ExecutePageHierarchy()
        {
            PopContext();
            StringWriter writer = new StringWriter();
            PushContext(new WebPageContext(), writer);
            base.ExecutePageHierarchy();
            PopContext();
            Response.Clear();
            string output = writer.ToString();
            output = output.Replace("<body>", "<body><h1>An Example of Filtering Razor Output</h1>");
            Response.Write(output);
            Response.End();
        }

        public override void Execute()
        {
        }
    }

 

 

          The above code simply adds two classes(generic and non generic version of FilterRazorOutput) and then inherits these classes from WebViewPage. These classes simply overrides the ExecutePageHierarchy and Execute methods. Execute is an abstract method. The above classes simply implement this method. During run time, this overriden method will never called because Razor view engine calls the dynamically created Execute method of dynamically generated view class.

 

          ExecutePageHierarchy method is called by Razor view engine during rendering HTML. So it's good place to see and filter the generated HTML. First, ExecutePageHierarchy method(shown above) simply pop the Response.Output text writer from the stack. Then it simply pushes a custom string writer in the stack. Then it call the base implementation of ExecutePageHierarchy method. Then it call the PopContext method again to write the generated HTML in the custom text writer and pop the custom text writer from the stack. Finally it simply filter the generated HTML by appending a h1 tag just after the body tag and then write the filtered HTML to the response and then ends the current request for further execution. 

 

          Now just register this new class with your view. So just open your razor view and add this at the top of the page and then run this application and see the effect.

 

@inherits FilteringRazorGeneratedOutput.Helpers.FilterRazorOutput

 

 

 Summary:

          In this article I showed you how easily you can see and filter the HTML generated by Razor view engine. This will help you when you need to change the generated HTML at run time or you need to log the generated HTML or when you need to set the different properties of Razor view at run time. Hopefully you will enjoy this article too. You can also download the sample application.

 

 

6 Comments

  • Hi Imran,
    this is amazing, very timely for me too.
    I'm running MVC 3.0 RC2 and the WebPageContext() object will no longer take 1 parameter.
    The line:
    PushContext(new WebPageContext(context: ViewContext.HttpContext), writer);
    can be replaced with:
    PushContext(new WebPageContext(), writer);
    Thanks for the work.

    Colin


  • If you make your class abstract you don't need to implement Execute()

  • @Jonas, Thanks for the tip.

  • Thx for this trick!

    when i using ExecutePageHierarchy and write the output, the vs debuger always throw an exception:"Server cannot set status after HTTP headers have been sent."

    The page is rendering but exception confused me a little. What is the problem?

  • Hi,

    I just override a Write method in the custom WebViewPage, and created a new HelperResult with manipulated output:

    public override void Write(HelperResult result)
    {
    string output = result.ToHtmlString().ToString();
    output = output.Replace("", "An Example of Filtering Razor Output");
    HelperResult hr = new HelperResult(w => w.Write(output));
    base.Write(hr);
    }

    The result is same as your solution.

  • @Lacc I don't get any exception

Comments have been disabled for this content.