Click here to Skip to main content
Click here to Skip to main content

Reducing the size of ASP.NET pages

By , 23 Nov 2009
 

Introduction

We all know when a page is requested, ASP.NET processes the page, its server controls, and finally sends the HTML to the client-side for the browser to render it. The time taken to download the HTML at the client side depends mainly on the final size of the page. If your page is data rich, it would take a lot of time to fetch it. So here I am presenting a technique to reduce the size of ASP.NET web pages.

Background

When you see a page's HTML source by clicking “View Source” in the browser, you could see that there are a lot of white space on the left side of each line on the HTML. This is actually a waste. Try saving the HTML page to your desktop and notice its size. Then delete all the spaces on the left side and then check its size. You could see that the size of the page reduces considerably, sometimes more than 50%!! (watch the View Source of Orkut in a browser).

Using the code

Here is a technique to achieve the same.

  1. Create a class in App_Code that derives from the System.Web.UI.Page class.
  2. public class MyPageBase : System.Web.UI.Page
    {
    }
  3. Replace System.Web.UI.Page in all your web pages (.aspx.cs) with MyPageBase. This means that now all your web pages are deriving from MyPageBase.
  4. Override the Render function in this class:
  5. public class MyPageBase : System.Web.UI.Page
    {
        protected override void Render(HtmlTextWriter writer)
        {
        }
    }
  6. Place the code below inside the function, and also write a support function as shown below:
  7. public class MyPageBase : System.Web.UI.Page
    {
        protected override void Render(HtmlTextWriter writer)
        {
                base.Render(htmlwriter);
                string html = htmlwriter.InnerWriter.ToString().Trim();
    
                if (ConfigurationManager.AppSettings["OptimizeHtmlOutput"] != "0")
                {
                    bool isAsync = !html.StartsWith("<");
    
                    if (!isAsync)
                    {
                        StringBuilder sb = MyPageBase._TrimHtml(html);
                        writer.Write(sb.ToString());
                    }
                    else
                    {
                        StringBuilder sb = new StringBuilder();
    
                        int startIx = 0;
                        while (true)
                        {
                            int x = html.IndexOf("|updatePanel|", startIx);
    
                            if (x > -1)
                            {
                                int xS = html.LastIndexOf("\r\n", x);
                                xS = (xS < 0 ? 0 : xS);
                                int xE = html.IndexOf("\r\n", x) + 2;
    
                                string header = html.Substring(xS, xE - xS);
                                header = header.Trim().TrimStart('|', ' ');
    
                                string sLen = header.Substring(0, header.IndexOf('|'));
                                int cLen = int.Parse(sLen);
    
                                string content = html.Substring(xE - 2, cLen);
                                content = MyPageBase._TrimHtml(content).ToString().Trim();
    
                                startIx = xE - 2 + cLen;
    
                                cLen = content.Length + 4;
                                header = (xS > 0 ? "|" : string.Empty) + 
                                          cLen.ToString() + 
                                          header.Substring(header.IndexOf('|'));
    
                                sb.AppendLine(header);
                                sb.AppendLine(content);
                            }
                            else
                            {
                                string stateData = html.Substring(startIx);
                                sb.Append(stateData.Trim());
    
                                writer.Write(sb.ToString());
                                break;
                            }
                        }
                    }
                }
                else
                {
                    writer.Write(html);
                }
            }
        }
    
        private static StringBuilder _TrimHtml(string source)
        {
            StringBuilder sb = new StringBuilder();
    
            source = source.Trim();
            using (StringReader sr = new StringReader(source))
            {
                string data = string.Empty;
                while (data != null)
                {
                    data = sr.ReadLine();
                    if (data != null)
                    {
                        data = data.TrimStart(' ', '\t');
                        if (data != string.Empty) sb.AppendLine(data);
                    }
                }
            }
    
            return sb;
        }
    } 

Notes

  1. Notice the usage of ConfigurationManager.AppSettings["OptimizeHtmlOutput"] != "0". You can define a key in the appsettings section of the web.config file to enable or disable this feature. Any value other than “0” will enable optimization.
  2. This code works well in AJAX based applications as well. Compare the size difference and performance by changing the flag. This is very beneficial especially in pages which contain a huge amount of data.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Aj 2010
Software Developer (Senior)
India India
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1memberstolbovoy1 Dec '09 - 5:10 
Gzip is the way to go. Removing extra tabs and spaces will not help much with gzip.
GeneralRe: My vote of 1, My Vote of 1 to your CommentmemberKronass5 Jan '10 - 8:15 
What he provided is not an alternative solution to compression, it is how to reduce the size of the page what ever with compression or not, it is always better to minimize the size of the page as much as possible even if you are using the compression specially if wasted spaces like Tags spacing
GeneralDid you check the differencememberAnurag Gandhi30 Nov '09 - 22:42 
Few Questions:
1. How much size you can reduce by doing this?
2. How much loading time you can save by performing such string operation?
 
I don't want to play with my Html Output on or after render because my inline JavaScript code doesn't work some times.
 
Anurag Gandhi.
http://www.gandhisoft.com
Life is a computer program and every one is the programmer of his own life.

GeneralMy vote of 1memberJacobs7630 Nov '09 - 21:49 
This is not good advice/approach.
 
Use built-in web server / asp.net features (Gzip)
GeneralRe: My vote of 1memberAj Ind30 Nov '09 - 22:07 
What about 1st reduce the size with this and then use Gzip ?
Besides Gzip requires more CPU utilization both in server and client side.
On low end machines, the browser looks still loading until the data is decompressed.
And the browser's HTML parser can save some time for trimming these white spaces and extracting and needed HTML for rendering.
GeneralWill corrupt <pre> text</pre>member~Anders30 Nov '09 - 21:15 
No, you cannot just remove whitespace, sometimes it's actually significant.
Off the top of my head, the <pre> tag comes to mind - I use this quite often for code snippets.
 
Look here
this is code line one
    line two indented four spaces
        line three indented eight spaces
    line four indentet two spaces
and no indentation in line five
 
Removing viewstate and using compression is the way to go.
GeneralRe: Will corrupt textmemberAj Ind30 Nov '09 - 22:02 
Yes you are rite. But u can simply extend this to override the PRE tags.
GeneralBetter ways to do this...memberRick Hansen30 Nov '09 - 10:23 
I cant give you high marks because this is not the best way to reduce page size.
 
The following two ways are the best:
 
1) Dont retain ViewState in the page, turn that off and retain ViewState on the server (in memory or SQL server) instead. There is an article on MSDN on how to implement this. ViewState is frequently very HUGE in .NET pages.
 
2) Turn on IIS HTTP compression for your web site, this is a very simple no-code-involved way to reduce page weight on the network transport. Browsers will decompress pages delivered by web servers implementing standard compression.
 
The method you present is really not the best approach, but nice try at solving the very important problem of page weight. .NET brought about many great changes, but retaining ViewState in the page payload was a big mistake in my opinion, fortunately there is a way to keep ViewState out of the page. It becomes especially bad when users need to HTTP POST a large page, as .NET only supports one FORM tag per page, posting all or nothing including the ViewState.
GeneralRe: Better ways to do this...memberAj Ind30 Nov '09 - 22:01 
Ofcourse there are other ways. Just only an additional technique to further reduce the size. See Orkut.com's view source
GeneralHttpResponse Filtermemberwebgruve30 Nov '09 - 10:23 
Hi,
 
This is not a bad technique, but you can also apply the same methodology by writing a response filter and handling it within a HttpModule. That will mean that you will not need to inherit a new class for all your pages and retrofit this to existing sites.
 
We have also been able to move and compress the viewstate using this method.
GeneralRe: HttpResponse FiltermemberAj Ind30 Nov '09 - 21:58 
Thanks for the suggestion.
GeneralMy vote of 2memberRick Hansen30 Nov '09 - 10:05 
Bad advice, IIS compression is the way to go, as well as not retaining page view state in the page, keeping view state on server will reduce page size.
GeneralRe: My vote of 2memberAj Ind30 Nov '09 - 21:46 
Ofcourse I know this technique is not the only way to reduce the page size.
Only an additional technique, dats all.
GeneralMy vote of 1membervissuch24 Nov '09 - 1:53 
?
QuestionAppendLine vs Appendmemberromgun23 Nov '09 - 21:33 
Is there any reason why you are using sb.AppendLine(data) insted of sb.Append(data)? By using sb.Append(data) you can shrink the page more.
AnswerRe: AppendLine vs AppendmemberAj Ind23 Nov '09 - 21:47 
Yes there is a reason. Consider below html fragments

<a href="/script/Content/Chapter.aspx?chptId=1"
onclick="return ToggleMenu('Chapter1')>My Content</a>

 
or
 

<a href="/script/Content/Chapter.aspx?chptId=1" onclick="return ToggleMenu('Chapter1')>My
Content</>

 
If you use Append instead of AppendLine then final html will be like as below
 
1. href="/script/Content/Chapter.aspx?chptId=1"onclick="return
2. MyContent
 
The spaces inside the HTML tags will also get trimmed, that may cause unexpected output
GeneralSuggest for modify your articlemembernicholas_pei23 Nov '09 - 14:07 
Hi guy,
I think you should give us a sample to show how many seconds your technique reduced.
eg: the normal loading time,and your special laoding time
GeneralRe: Suggest for modify your articlememberAj Ind23 Nov '09 - 16:14 
Will give u a comparison shortly.
GeneralBug fixed!memberAj Ind23 Nov '09 - 6:02 
Update the code as below
 
protected override void Render(HtmlTextWriter writer)
{
using (HtmlTextWriter htmlwriter = new HtmlTextWriter(new StringWriter()))
{
.........
Existing code
.........
}
}
GeneralGZIP is the way to go .membervissuch23 Nov '09 - 5:50 
Just enabling GZIP will do wonders for you, you really do not need to think about removing the white spaces and all.
AnswerRe: GZIP is the way to go .memberAndre Luiz V Sanches23 Nov '09 - 8:01 
That raises two problems: CPU utilization and output caching. Myself, for one, can't use http compression because of those two.
 
My point is: don't take things for granted, it just shows you're lazy.
 
Nice article, can't wait to try it.
 
---------
Andre Sanches
 
"UNIX is friendly, it's just picky about its friends"

GeneralRe: GZIP is the way to go .membervissuch23 Nov '09 - 11:25 
Agreed. Smile | :)
 
Just to make this discussion more complete, in the IIS there are levels for gzip from 1-10. I think if you really do not want batter your cpu you can set it to low. For most people 8-9 kind of works optimally, but may be 2 or 3 will be good for the CPU's your are using.
 
There is another idea where like in this article your are sending the stripped version of your HTML page you can send the gzipped version, but the page it self gzipping. I think this can take care of the page output caching.
 
Anyway this are some of the options I am providing over here.
 
As with everything else, this might not be the solution for everyone.
GeneralDont work!!memberraphaelm2223 Nov '09 - 5:15 
Where it came from the variable "htmlWriter"
GeneralRe: Dont work!!memberAj Ind23 Nov '09 - 6:03 
Thanks for pointing it out...missed some code..
GeneralRe: Dont work!!memberAj Ind23 Nov '09 - 6:07 
This is my 1st in codeproject...do u have any idea how to modify the article ?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 23 Nov 2009
Article Copyright 2009 by Aj 2010
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid