Http Compression in ASP.Net
Yesterday I got a chance to attend web performance optimization team meeting, and they suggested, HTTP Compression will help to reduce the Bandwidth and thus improves the performance. Later I come to know some of other teams in my organization are using these techniques in their web applications. I found few implementations, and the code is written in Global.asax. But the problem with this approach is the code is not reusable. I thought of implementing it an Http Module for compressing the HTTP response. For more information about HttpModules, check MSDN.
Here is the code of Compression Module.
public class CompressionModule : IHttpModule
{
private HttpApplication httpApplication;
private string acceptEncoding;
private const string DEFLATE = "deflate";
private const string GZIP = "gzip";
private const string AJAX = "HTTP_X_MICROSOFTAJAX";
private const string WEBSERVICE = "SyncSessionlessHandler";
/// <summary>
/// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
/// </summary>
public void Dispose()
{
//Do nothing
}
/// <summary>
/// Initializes a module and prepares it to handle requests.
/// </summary>
/// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param>
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
this.httpApplication = context;
}
/// <summary>
/// Handles the BeginRequest event of the context control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void context_BeginRequest(object sender, EventArgs e)
{
if (IsEncodingSupported)
{
//Converting the Accept encoding to lower, it can be gZip, GZip, Gzip
this.acceptEncoding = acceptEncoding.ToLower();
Stream prevUncompressedStream = this.httpApplication.Response.Filter;
//First checks whether deflate compression is supported or not.
//Because Deflate offers better compression compared to GZip
if (acceptEncoding.Contains(DEFLATE) || acceptEncoding == "*")
{
// defalte
this.httpApplication.Response.Filter = new DeflateStream(prevUncompressedStream,
CompressionMode.Compress);
this.httpApplication.Response.AppendHeader("Content-Encoding", DEFLATE);
}
else if (acceptEncoding.Contains(GZIP))
{
// gzip
this.httpApplication.Response.Filter = new GZipStream(prevUncompressedStream,
CompressionMode.Compress);
this.httpApplication.Response.AppendHeader("Content-Encoding", GZIP);
}
}
}
/// <summary>
/// Gets a value indicating whether this instance is encoding supported.
/// </summary>
/// <value>
/// <c>true</c> if this instance is encoding supported; otherwise, <c>false</c>.
/// </value>
private bool IsEncodingSupported
{
get
{
//Check wheather the Request is for Page or Web Service.
//Also check wheather it an AJAX Request.
this.acceptEncoding = this.httpApplication.Request.Headers["Accept-Encoding"];
if (!this.httpApplication.Request.RawUrl.Contains(".aspx") ||
this.httpApplication.Request[AJAX] != null)
{
return (false);
}
//Check whether browser supports compression.
if (acceptEncoding == null || acceptEncoding.Length == 0)
{
return (false);
}
return true;
}
}
}
As the code is in App_Code folder, you need to register the http module in the Web.Config file.
<httpModules>
<add name="CompressionModule" type="CompressionModule, App_Code"/>
</httpModules>
If you are using IIS 7 the settings will be different like this.
<system.webServer>
<modules>
<add name="CompressionModule" type="CompressionModule, App_Code"/>
</modules>
</system.webServer>
