About the author

Miron Abramson
Me
Software Engineer, Senior Developer at CapitalIQ, and .NET addicted for long time.
Open source projects:
MbCompression - Compression library

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Creative Commons License

Blog Flux Directory
Technology Blogs - Blog Top Sites

Compress your pages, css, js and WebResources.axd files for better performance

(See updated post:  New & Shiny WebResource.axd compression Module

This post is an update for my previews post about http compression. In that post, I posted a http module that compress aspx pages and WebResource.axd files.
Thanks to Mads Kristensen, that found a performance issue in my code and had a solution for that, I improved my compressor component and also I included a complete project to compress asp.net pages, CSS files, JavaScript files and WebResource.axd files as well. The implementation in really very simple and not lot of changes are necessary in existing project. The page compression is very simple, and common to all http compressors:
 Registering the httpmodule in the web.config:

<add name="HttpCompressionModule" type="Miron.HttpHandlersAndModules.HttpCompressionModule"/>

and the compression itself in the httpmodule: 

HttpApplication app = sender as HttpApplication; 

// Check if GZIP is supported by the client

if (IsGzipEncodingSupported())
{
    app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);

    SetEncodingType(GZIP);   // Set the response encoding type header
}
// Check if DEFLATE is supported by the client
else if (IsDeflateEncodingSupported())
{
    app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);

    SetEncodingType(DEFLATE);  // Set the response encoding type header
}

The WebResource.axd compression is a bit more complicate, but the idea is to make a 'fake' request based on the requested url when the client asked for WebResource.axd file, get the response into byte[], compress it into MemoryStream cache it as a byte[] and send it to the client. The next time the client ask for this WebResource, it served from the cache (thanks again to Mads Kirstensen). The compression is only when the WebResource serve css or javascript files. over wise, the WebResource is send to the client 'as it'.   The CSS and the JS files compression is similar to the page compression, the differents  are that in those cases, we load the requested file, read it into string, manipulate it  (remove unneeded spaces and stuff), compress it, cache it, and send it to the client. The 'problem' is that css and js files are served by the IIS itself, and not by ASP.NET engine, so what we do is, changing the 'src' attribute for js files to jslib.axd or the 'href' attribute for css files to css.axd, and add as query string the real files name (see in the ReadMe.txt file how it done), and those files are handled by ASP.NET engine and to compress tham - for that, we register the following handlers in the web.config: (another option, is to serve those files via WebResources)

<add verb="*" path="jslib.axd" type="Miron.HttpHandlersAndModules.JavaScriptHandler" validate="false"/>

<add verb="*" path="css.axd" type="Miron.HttpHandlersAndModules.CssCompressionHandler" validate="false"/>

The caching for those files have CacheDependency on the files, so the content is removed from the cache in the moment the files are changed, and reload again when requested. Before sending data to the client, we check the ETag, and if its the same as the client sent, so we can stop the response and send only the code 304. 

Extra features

By configuration in the web.config, it is possible to disable any compression type, decide the time (by days) the cached file will be in the cache, and also it is possible to specified mimeTypes content to not compress or specified aspx files to exclude from the compression.  All configuration description in the ReadMe.txt file. 

 Implementation 

All implementation instructions are in the attach zip file in ReadMe.txt file.

Note

The WebResource compression may not work if the request is url that modified in the windows 'host' file. In that case, you will need to disable WebResource compression (See in the  ReadMe.txt)

  (See update post with new & better code: New & Shiny WebResource.axd compression Module)

Latest code can be downloaded from:

http://www.codeplex.com/MbCompression

Currently rated 4.0 by 6 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Miron on Monday, September 24, 2007 8:17 AM
Permalink | Comments (7) | Post RSSRSS comment feed

Related posts

Comments

Joao pt

Tuesday, March 25, 2008 1:42 AM

Joao

Why is there an exception for IE6 browser?

Miron il

Tuesday, March 25, 2008 2:10 PM

Miron

Hey Joao,
IE6 have a well known problem with compression that described here:
http://support.microsoft.com/kb/312496
Still there are lots of users that using IE6, so, better for them to get not compressed data then corrupted data...
If you are interesting in the compression module, I suggest you to read the updated post:
mironabramson.com/.../...d-compression-Module.aspx

John Dillon gb

Wednesday, April 30, 2008 7:12 AM

John Dillon

Fantastic work thanks you very much for sharing this. One small issue I get is that I get an error when I set comPressPage=true?

Here are the settings: <CompressorSettings reflectionAlloweded="true" optimizeHtml="true" daysInCahe="1" compressCSS="true" compressJavaScript="true" compressPage="true" compressWebResource="true" compressThirdParityScripts="true">

Here is the error:

'/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl00_RadScriptManager1_HiddenField&amp;_TSM_CombinedScripts_=%3b%3bTelerik.Web.UI%2c+Version%3d2008.1.416.35%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3a2b085cdb-b44c-4804-80d3-9ac9bd7a0568%3a393f5085%3a9703c1f0%3aa3f85c94%3a6cfd3594%3af2a57eb7%3a665c7bcf%3ac6335cbd%3a526d426%3a4b40c3e6%3a4fc2fd6d%3a34f9d57d" type="text/javascript' is not a valid virtual path.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: '/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl00_RadScriptManager1_HiddenField&amp;_TSM_CombinedScripts_=%3b%3bTelerik.Web.UI%2c+Version%3d2008.1.416.35%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3a2b085cdb-b44c-4804-80d3-9ac9bd7a0568%3a393f5085%3a9703c1f0%3aa3f85c94%3a6cfd3594%3af2a57eb7%3a665c7bcf%3ac6335cbd%3a526d426%3a4b40c3e6%3a4fc2fd6d%3a34f9d57d" type="text/javascript' is not a valid virtual path.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


[HttpException (0x80004005): '/Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl00_RadScriptManager1_HiddenField&amp;_TSM_CombinedScripts_=%3b%3bTelerik.Web.UI%2c+Version%3d2008.1.416.35%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3a2b085cdb-b44c-4804-80d3-9ac9bd7a0568%3a393f5085%3a9703c1f0%3aa3f85c94%3a6cfd3594%3af2a57eb7%3a665c7bcf%3ac6335cbd%3a526d426%3a4b40c3e6%3a4fc2fd6d%3a34f9d57d" type="text/javascript' is not a valid virtual path.]
System.Web.VirtualPath.Create(String virtualPath, VirtualPathOptions options) +3626815
System.Web.VirtualPathUtility.ToAppRelative(String virtualPath) +10
Miron.Web.HandlersAndModules.Filters.PrepareScriptsToComnpression.Replace(Match m) +102
System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) +217
System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator, Int32 count, Int32 startat) +28
System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) +45
Miron.Web.HandlersAndModules.Filters.PrepareScriptsToComnpression.Found(Match m) +87
System.Text.RegularExpressions.RegexReplacement.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat) +217
System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator, Int32 count, Int32 startat) +28
System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator) +45
Miron.Web.HandlersAndModules.Filters.PrepareScriptsToComnpression.FixScriptsUrl(String html) +72
Miron.Web.HandlersAndModules.Filters.PrepareScriptsToComnpression.Write(Byte[] buffer, Int32 offset, Int32 count) +59
System.Web.HttpWriter.Filter(Boolean finalFiltering) +251
System.Web.HttpResponse.FilterOutput() +97
System.Web.CallFilterExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +54
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64


Miron il

Sunday, May 04, 2008 3:10 PM

Miron

@John,
Download the updated code (last update at 05-05-08) from the post: mironabramson.com/.../...-third-party-scripts.aspx
It should work fine. Let me know if any problems.

Rajesh in

Monday, June 09, 2008 10:36 PM

Rajesh

Hi,
I am getting the following error when I try to use your code

Server Error in '/gacvolonline' Application.
--------------------------------------------------------------------------------

Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: Could not load type 'Miron.HttpHandlersAndModules.HttpCompressionModule'. (C:\GACvolOnline\web.config line 91)

Source Error:


Line 89: <httpModules>
Line 90: <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
Line 91: <add name="HttpCompressionModule" type="Miron.HttpHandlersAndModules.HttpCompressionModule"/>
Line 92: <add name="WebResourceCompressionModule" type="Miron.Web.HandlersAndModules.WebResourceCompressionModule"/>
Line 93: </httpModules>


Source File: C:\GACvolOnline\web.config Line: 91


--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:2.0.50727.1433; ASP.NET Version:2.0.50727.1433

Yaseen

Sunday, June 29, 2008 8:14 PM

Yaseen

It is good work, but in my case i want to compress a Query string how can I accomplished this task

Miron il

Sunday, June 29, 2008 11:11 PM

Miron

@Rajesh,
I looks problem with the configuration.
Take the last code and info from latest post:
www.mironabramson.com/.../...mpression-Module.aspx

@Yaseen,
What do you mean by 'compress a Query string' ?

Add comment


(Will show your Gravatar icon)  

  Country flag





Live preview

Sunday, September 07, 2008 4:04 AM