The output of most ASP.NET pages is in the form of text. In the terms of HTTP, the content-type is called "text/html". The text received by the client browser, from the ASP.NET page on an IIS Web Server, is then rendered on your computer screen. Since this communication takes place over the internet, it consumes bandwidth. For instance, a 40 KB ASP.NET page will take exactly 40 KB of network bandwidth (plus the bandwidth for headers sent and received by the client browser). To optimize this communication cycle, HTTP Gzip and Deflate compression is used. HTTP compression will enable a 40 KB output from an ASP.NET page to be compressed using Gzip or Deflate compression to as low as 12-15 KB, thus saving 25-28 KB of network bandwidth. Now consider the implications of this network bandwidth savings over hundreds of thousands of requests handled by IIS Server each day. This can be huge? Isn't it? Add to this the fact that to the users accessing your website, your website will load faster and will thus improve the user experience and perception of your website.
How to enable HTTP Compression in our ASP.NET pages?
Now that you understand, how important HTTP compression can be for your website and its visitors, we will discuss what is required to achieve HTTP Gzip and Deflate compression in our ASP.NET websites. The first thing that you should know is that HTTP compression is of two types, it can be Gzip or Deflate. To use HTTP compression in our ASP.NET pages without editing every single one of them, we will make use of ASP.NET web application life cycle events in Global.asax file.
A Global.asax file is placed in your ASP.NET application folder. It can contain methods to handle ASP.NET web application life cycle events. The names and details of all web application events that we can handle in Global.asax file is beyond the scope of this tutorial. But one event that we will handle and where we will insert our code is PreRequestHandlerExecute. It occurs just before ASP.NET starts executing an event handler. The complete method signature to handle this event is displayed below:
void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
...
}
Note: The naming convention used by ASP.NET to bind application events like PreRequestHandlerExecute with actual event handlers is to use the name of object who fires the event, in this case Application, with the underscore (_) character and then finally comes the event name itself, which in our case is PreRequestHandlerExecute.
Why our default HTTP Compression Method will be Deflate?
We will be using Deflate HTTP compression by default because it offers faster compression and decompression than Gzip. For more details, please read this article: Gzip vs Deflate: Which is the faster HTTP compression method?
Global.asax
Ok folks, let's cut the details and go straight to the code. If your ASP.NET web application doesn't already contain a Global.asax file, create a new one using notepad. Then insert following code in it:
<%@ Application Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO.Compression" %>
<script runat="server">
void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
string acceptEncoding = app.Request.Headers["Accept-Encoding"];
Stream prevUncompressedStream = app.Response.Filter;
if (!(app.Context.CurrentHandler is Page ||
app.Context.CurrentHandler.GetType().Name == "SyncSessionlessHandler") ||
app.Request["HTTP_X_MICROSOFTAJAX"] != null)
return;
if (acceptEncoding == null || acceptEncoding.Length == 0)
return;
acceptEncoding = acceptEncoding.ToLower();
if (acceptEncoding.Contains("deflate") || acceptEncoding == "*")
{
// defalte
app.Response.Filter = new DeflateStream(prevUncompressedStream,
CompressionMode.Compress);
app.Response.AppendHeader("Content-Encoding", "deflate");
} else if (acceptEncoding.Contains("gzip"))
{
// gzip
app.Response.Filter = new GZipStream(prevUncompressedStream,
CompressionMode.Compress);
app.Response.AppendHeader("Content-Encoding", "gzip");
}
}
</script>
Explanation
Guys, the above code is all that is required to enable HTTP compression in your ASP.NET pages. This is true, pretty simple stuff. Let us now focus on the details of the code presented above.
The first thing we do is to tell the ASP.NET compiler that the forthcoming code is going to be in the language, C#.
<%@ Application Language="C#" %>
Next, we import the namespaces that our code will make use of. Remember, the GZipStream and DeflateStream classes are new in ASP.NET 2.0 and are present in the System.IO.Compression namespace.
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO.Compression" %>
Next, we declare the method that will handle the PreRequestHandlerExecute life cycle event. As explained earlier, this event occurs just before ASP.NET starts executing an event handler.
void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
...
}
Next, we properly cast the sender Object, using the as keyword, into a variable of type HttpApplication, because this is the object that fired this event to begin with. Using this object, we fetch the headers collection sent by the client-browser. Specifically, we are interested in a "Accept-Encoding" header. If a client browser supports compressed content streams (which most browsers do) of the types, Gzip and Deflate, the value of this header will contain them. A reference to current uncompressed output Stream object used by ASP.NET to send the plain text (or binary) output to the client browser is saved in the prevUncompressedStream object.
We try to make sure that the requested ASP.NET resource is either a valid ASP.NET page or a Web Service. If it is not, then we return and do nothing. Additionally, we also check for "HTTP_X_MICROSOFTAJAX" item in the HttpRequest collection. This item is often present when using AJAX in ASP.NET pages. When the ASP.NET content is compressed when AJAX is being used, the page can throw exceptions. So we play safe, and don't compress the page if AJAX is being used.
Note: You can now enable HTTP Compression not only in your ASP.NET web pages but in your ASP.NET web services as well. All you have to do is to also check for the name of the type of CurrentHandler property and match it with "SyncSessionlessHandler". It will only match if it is a Web Service. And that's it.
Thanks Scott Gartner!
Finally, we check to see if either the client browser did not send the "Accept-Encoding" header, or if it did send, but its value is empty, will mean that client-browser cannot process compressed content. In that case, we simply return from this method and do nothing
HttpApplication app = sender as HttpApplication;
string acceptEncoding = app.Request.Headers["Accept-Encoding"];
Stream prevUncompressedStream = app.Response.Filter;
if (!(app.Context.CurrentHandler is Page ||
app.Context.CurrentHandler.GetType().Name == "SyncSessionlessHandler") ||
app.Request["HTTP_X_MICROSOFTAJAX"] != null)
return;
if (acceptEncoding == null || acceptEncoding.Length == 0)
return;