Friday, July 1, 2011

Speed up your ASP.NET site with compression(GZip Compression)

Loading speed is a crucial issue for every professional web site. If your website takes too long to load, your visitors, who are your potential customers, will go away and never come back no matter how much effort you have put to develop a professional code or design a charming user interface. There are several techniques to speed up your website, pre creation of pages, caching … and compression.
Server level and page level compression

Compression can be performed in two stages: IIS and each individual web site. If you enable compression on IIS (6.0 and later),. all web sites and virtual directories are affected. Therefore, this technique is recommended only if you have the full control over that server and you own all the web sites on it. You must also get sure that all web sites on the server have no problem with getting compressed. If there are several web sites on the server who you are not the owner or administrator of them, you would better not bother by trying to compress them.
Page level compression lets you compress your own web site or even only specific pages or file types. For example we can set our compression mechanism to compress .aspx files only, and not html files, or not pages that use ASP.NET Ajax controls.
What do I need?

If you are using ASP.NET 2.0 and above (not 1.1) you do not need any 3rd party compression module or tool. All you need is provided by .NET Framework.
How to do it?

All we need to do is to compress the response output. It can be easily done by GzipStream or DeflateStream classes. Both of them use the same algorithm and the only difference is that GzipStream stores more header information on compressed file/stream to be used by 3rd party zip tools. Therefore DeflateStream is more light-weight. Before we compress the response output, we should get sure that the page we are doing to compress, supports compression. Otherwise, the user’s browser might not be able to decompress and display the page.
There are two ways of enabling response compression: First via HttpHandlers and Web.Config file, second by adding some code to global.asax file. Using a HttpHandler lets you change your compression module later without recompiling your web application and re-deploying it.
To compress the response output, all you need to do is to compress the Response.OutPut and assign it to Response.Filter. Response.Filter allows you wrap the Response.Output before it is transmitted towards the web browser.

context.Response.Filter = new
DeflateStream(context.Response.OutputStream,CompressionMode.Compress);

To create a HttpHandler, add a new class library project to your solution, including a public class which inplements IHttpHandler interface. Then implement it as the following code:
public
class
CompressMe:IHttpHandler

{

:

public
void ProcessRequest(HttpContext context)

{

string pageEncoding = context.Request.Headers["Accept-Encoding"];

if (!string.IsNullOrEmpty(pageEncoding))

if (pageEncoding.ToLower().Contains(“gzip”))

{

context.Response.AppendHeader(“Content-encoding”, “gzip”);

context.Response.Filter = new
GZipStream(context.Response.Filter, CompressionMode.Compress);

} }
As seen in the above code, first we check to see if the page header indicates compression is supported or not. If it is supported, we create a new instance of DeflateStream (belongs to .NET Framework 2.0 +) and pass Response. Filter to it. This is the stream that we like to compress. The resulting stream is assigned to Response.Filter , meaning that a compressed copy of Response. Filter is transmitted to the browser.
The context.Response.AppendHeader(“Content-encoding”, “gzip”) thing says the browser that it must decompress the page before displaying it. Today’s browsers usually are smart enough to figure it out, but better safe than sorry.
Now build the class library and copy it into /bin folder of your web site or reference to it from within your web application. Suppose that your class library is called CompressionModule, it includes a namespace called CompressionModule and class named CompressMe (which implements IHttpHandler interface). Now add the following line of code to web.config file, under <httpHandlers> tag:
<add
verb=*
path=*.aspx
type=

CompressionModule.

CompressionModule,

CompressMe

/>

This means that all .aspx files, with both GET and POST methods, must be redirected to CompressMe class before being sent to the browser.
NOTICE: YOU MUST RUN YOUR WEB SITE UNDER IIS AND NOT VISUAL STUDIO DEVELOPMENT SERVER. OTHERWISE YOUR PAGE SIZE WILL BE ZERO BYTES.
Another way to activate the compression is to implement Application_PreRequestHandlerExecute in global.asax file. To do so, add an event handler to global.asax file, convert sender argument to HttpApplication and use its Reponse property exactly like you did in above code:
void Application_PreRequestHandlerExecute(object sender, EventArgs e)

{


HttpApplication app = sender as
HttpApplication;

…………

}

More benefits of compression in ASP.NET applications

Compression can even be more of help in your ASP.NET web site. For example you can compress uploaded files, especially if you store them in a data base since databases are very expensive and accessing them is time/resource consuming.
The following code demonstrates how to compress an uploaded file and save it:
As the code exposes, we access to the uploading file via FileUpload.PostedFile.InputStream which helps us to create a GzipStream object based on it. We also create a FileStream to store the compressed file in a .zip file. Afterwards, we start to read 2048-byte packets of the GzipStream and write it into the FileStream. That’s all J

private
void DoUpload(FileUpload fileUpload)

{


const
int bufferSize = 2048;


string fileName = Path.ChangeExtension(Path.Combine(Server.MapPath(Request.Url.AbsolutePath), fileUpload.PostedFile.FileName), “.zip”);


FileStream fs = new
FileStream(, FileMode.Create);


GZipStream zip = new
GZipStream(fileUpload.PostedFile.InputStream, CompressionMode.Compress);


try

{


byte[] buffer = new
byte[bufferSize];


int offset = 0;


int count = 0;

count = zip.Read(buffer, offset, bufferSize);


while (count > 0)

{

fs.Write(buffer, offset, count);

offset += count;

}

}


finally

{

fs.Close();

zip.Close();

}

}