Eliminating Whitespace in the Page Response
One of the many features that makes ASP.NET applications so convenient to develop is the ability to mix traditional html (or xhtml) with server controls. What's even more convenient is that the markup that is output by the page preserves the formatting of the source and outputs the control content with (relatively) well formatted markup accordingly. When trying to pinpoint trouble spots, having formatted output makes it easy to read through the page's html output.
This formatting is provided by adding new-line and tab characters into the page output. When the browser interprets this html, it ignores these extra whitespace characters. Therefore, in a productions environment, the whitespace characters are just unnecessary overhead that increase the overall size of the page.
Fortunately, the .NET Framework makes it very easy to eliminate this overhead by simply overriding a couple of methods. All the html content output by an ASP.NET page is generated by an HtmlTextWriter. The HtmlTextWriter provides a series of methods that simplifly generating html tags and attributes in an html document. Fortunately, the Page class allows you to override the method used for creating the HtmlTextWriter used to generate the html response. In addition, the two methods used to provide the formatting characters have been marked virtual - making it easy to override them.
First we'll create a new HtmlTextWriter class:
public class CompactHtmlTextWriter : HtmlTextWriter { public CompactHtmlTextWriter(System.IO.TextWriter writer) : base(writer) { } public CompactHtmlTextWriter(System.IO.TextWriter writer, string tabString) : base(writer, tabString) { } public override void WriteLine() { //base.WriteLine(); } protected override void OutputTabs() { //base.OutputTabs(); } }
I've simply overidden the WriteLine and OutputTabs methods so that they do nothing. Next, we'll need to ensure that our pages utilize our new CompactHtmlTextWriter instead of a normal HtmlTextWriter. To do so, we'll need to create a BasePage that we can use to derive our new pages from:
public class BasePage : System.Web.UI.Page { protected override HtmlTextWriter CreateHtmlTextWriter(System.IO.TextWriter tw) { if (HttpContext.Current.IsDebuggingEnabled) { return base.CreateHtmlTextWriter(tw); } return new CompactHtmlTextWriter(tw); } }
Here, I've overidden the Page's CreateHtmlTextWriter method to return and instance of our new CompactHtmlTextWriter class if the has it's debug setting turned off (as it would be in a production environment). Otherwise, the page will utilize it's original behavior.
Now all that's left to do is to modify that pages in our site to utilize our BasePage class instead of the standard System.Web.UI.Page. This can be accomplished in a couple of ways. If you're using the inline code model, then you have two options. First, you can specify the base class of individual pages by setting the Inherits attribute in the Page directive like so:
<%@ Page Language="C#" Inherits="BasePage" %>
Alternatively, you can set the pageBaseType attribute of the pages tag in the web.config like so:
<?xml version="1.0"?>
<configuration>
<system.web>
<pages pageBaseType="BasePage"/>
</system.web>
</configuration>
If you are using the code-behind model for your pages, then simply change the class your page's code-behind class inherits from from
public partial class Default2 : System.Web.UI.Page
to
public partial class Default2 : BasePage
Please note that the code above is for a Visual Studio Web Site project - If you're using the Web Application project, you may have to make some changes. I have posted a zip file of a sample Web Site that demonstrates this. If there is interest in a sample that uses the Web Application project, send me a note and I can get that up too.
That's it! Eliminating all that extra whitespace can really add up - especially on large pages. You may see a savings of as much as 10%. It may not sound like much, but over the course of the lifetime of an application, that can really add up. Happy coding!