Thursday, April 30, 2015

ASP.Net C# Override Render event to get and manipulate page content before it's rendered

Here's an easy way to intercept the content that an ASP.Net page is going to render and send back to the browser.
   protected override void Render(HtmlTextWriter Writer)  
   {  
      // variables
      string Content = string.Empty;  
   
      // get the fully rendered content of this page so we can do some additional translations if necessary  
      using (StringWriter StringWriter = new StringWriter())  
      {  
         using (HtmlTextWriter HtmlTextWriter = new HtmlTextWriter(StringWriter))  
         {  
            // render current page content to temp writer  
            base.Render(HtmlTextWriter);  
   
            // close writer  
            HtmlTextWriter.Close();  
   
            // get content  
            Content = StringWriter.ToString();  

            // DO SOMETHING WITH THE CONTENT
         }  
      }  

      // render content
      Writer.Write(Content);
   }

Using the override keyword for the Render event lets you get and manipulate the content before it's rendered. Using the example above, the Content string variable will hold the content that will be rendered back to the browser. Now you could manipulate the content before it is rendered. A good example would be some kind of string replacement. Say for example you want to define a custom pattern and use it through your pages, content, resource files, and such. In that case you could use the following code where the DO SOMETHING WITH THE CONTENT comment is.

   // look for <translate></translate> pattern so we can translate them on the fly  
   foreach (Match m in Regex.Matches(Content, @"<translate>(.*?)</translate>", RegexOptions.IgnoreCase))  
   {  
      // get the pattern
      // e.g. <translate>lblFirstName</translate>   
      string Pattern = m.Value.ToLower();

      // remove the pattern so you are left with just the ID
      // e.g. lblFirstName
      string ID = Pattern.ReplaceValue("<translate>", string.Empty).ReplaceValue("</translate>", string.Empty);

      // do some kind of lookup with the ID
      // e.g. This could be something as simple as getting a value from a resource file for a specific language
      string Translation = "Lookup value for the current ID";
   
      // do a string replacement on the Content variable replacing the pattern with your translation
      Content = Content.ReplaceValue(Pattern, Translation);
   }  

The above code is dependent upon a simple ReplaceValue extension method:
   public static string ReplaceValue(this string Value, string Pattern, string Replacement)  
   {  
      return Regex.Replace(Value, Regex.Escape(Pattern), Replacement, RegexOptions.IgnoreCase);  
   }  

This is a simplified version of a solution that I use regularly, and it works really well. This idea sort of evolved over time to handle more complex scenarios were you don't always have the luxury of using simpler techniques. For example, at first glance you might just think about using a simple resource file on your ASPX page. That can work for a lot of situations. Another thought would be to use a custom user control where you can define a "key" attribute and do your resource lookup within the user control. Again, a very good solution that can cover most situations; however, this particular pattern replacement technique allows you to handle other situations where you have data that is not directly within your ASPX page, for example, other resource files, or data from a database, etc.

The pattern can be used literally anywhere on the page. Whether it's in your JavaScript, HTML, or even part of a more complex ASP.Net web control, for example:

JavaScript:
 alert("<translate>FirstNameRequired</translate>");  

HTML:
 <div><translate>lblDisclaimer</translate></div>  

GridView:
 <asp:BoundField DataField="FirstName" HeaderText="<translate>lblFirstName</translate>" HtmlEncode="false" />  

How it's used is really limitless, and for language driven websites, it can be a really nice way to make things more generic and flexible.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

0 comments: