Some weeks ago I wrote how to minify and compress the WebResource.axd handler. In the comments of that post someone asked how to do the same with ScriptResource.axd. I thought about it and realized it could be done much smarter.

If you take a look at the HTML source at the CodePlex Issue Tracker page, you’ll see it references 13 WebResource.axd and ScriptResource.axd. That’s 13 different web requests on each page load. The ScriptResource.axd is using HTTP compression but WebResource.axd does not. None of them minifies the scripts.

Therefore it would be cool to create a plug ‘n play HttpModule that combines all resource.axd scripts into one single web request and then minify and compress them. It would result in smaller HTML, fewer web requests and optimized JavaScript code. If you’re a YSlow nazi like me, this is a must-have.

How it works

To make it work, we need both an HttpModule and an HttpHandler.

The module

The module looks for resource scripts in the HTML code and collects all the references from the src tag. It then constructs a new script tag containing all the references and points it to the HttpHandler. The new script tag is injected into the HTML where the first resource script was found. It keeps the order of the scripts intact.

All the original scripts are now removed and a single new script pointing to the handler is injected.

The handler

When the handler is requested by the browser it looks for a URL parameter containing the references to the original resource script. They are separated by a comma in the URL parameter. It then retrieves the content of each script using a HTTP request. Then content is then aggregated into a single string which then get’s minified. Minifying means that all comments and whitespace is removed from the script.

The string is then being cached so the handler only has to do it once per application life cycle. The output is then compressed and the appropriate header set so the browser will cache the file for 30 days. You can easily set the number of days in cache to whatever you see fit.

Implementation

Download the ScriptCompressor.cs file below and put it in your App_Code folder. Then add the following lines to your web.config:

<httpModules>
  <add type="ScriptCompressorModule" name="ScriptCompressorModule" />
</httpModules>
<httpHandlers>
  <add verb="*" path="*js.axd" type="ScriptCompressorHandler" />
</httpHandlers>

Download

ScriptCompressor.zip (3.43 kb)

Today, I’ve been updating the BlogEngine.NET Gravatar support to include the new fallback types that Gravatar introduced a few months ago.

A Gravatar is an image that is associated with an e-mail address if the owner of the e-mail address has registered with Gravatar.

If an e-mail address doesn’t have an associated image, Gravatar serves a fallback image instead. Before, the fallback image could either be the default blue Gravatar logo or a URL to an image on the web. Now they have introduced three new fallback image types:


MonsterID


Identicons


Wavatars

This is really cool because now we don’t need to implement our own fallback images in BlogEngine.NET or any other web application for that matter. BlogEngine.NET has had its own implementation of the MonsterID and Subtext uses Identicons. Now none of these projects have to maintain that code anymore. I just deleted all the MonsterID images and that freed several megabytes of disk space.

Example

Here is an example on how to use the new Gravatar fallback types in ASP.NET. First we have to create a method that generates the correct Gravatar URL:

/// <summary>

/// Creates a URL to the Gravatar associated with the email address.

/// </summary>

/// <remarks>

/// The fallback parameter can either be a fully qualified URL to a custom

/// image located on the web or it can be "monsterid", "wavatar" or "identicon".

/// In case a null or an empty string is passed as a fallback, the default blue

/// Gravatar image will be shown.

/// </remarks>

/// <param name="email">The email is the key to find the right Gravatar.</param>

/// <param name="size">The size of the returned Gravatar in pixels.</param>

/// <param name="fallback">The fallback if no Gravatar exists.</param>

/// <returns></returns>

public static string Gravatar(string email, int size, string fallback)

{

  if (string.IsNullOrEmpty(email))

    throw new ArgumentNullException("email", "Email must be specified");

 

  if (!string.IsNullOrEmpty(fallback) && fallback.StartsWith("http"))

    fallback = HttpUtility.UrlEncode(fallback);

 

  email = email.ToLowerInvariant().Trim();

  string hash = FormsAuthentication.HashPasswordForStoringInConfigFile(email, "MD5").ToLowerInvariant();

  return "http://www.gravatar.com/avatar/" + hash + ".jpg?s=" + size + "&d=" + fallback;

}

And then call it from an image tag on the web page.

<img src="<%=Gravatar("mail@example.com", 60, "wavatar") %>" alt="Gravatar" />

It's as simple as that.