Optimize Your ASP.NET Mobile Website Using the Data URI Scheme

Leverage a little-known but widely supported browser feature: the data URI scheme

Dino Esposito

December 14, 2011

8 Min Read
ITPro logo

Images have always been linked to websites as external resources. The <img> HTML tag offers the src attribute for you to indicate the URL fromwhich the browser can download the desired image. Depending on the settings, the image may then be cached locally to save you additional downloads whenthe host page is reloaded or refreshed. This model is the most common way of linking images from web pages, both desktop and mobile. It is not the onlypossible approach, though. In addition to linking the image using a URL endpoint, you can embed the image bits in the host page. In this way,downloading the image doesn't require an additional HTTP request.

In general, reducing the number of HTTP requests required to load a web page makes the page load much faster. Minimizing the number of requests iscommonly applied to script and Cascading Style Sheets (CSS) files, which are sometimes merged into a single file when not embedded as plain text in thepage. Optimizing the download of images typically means creating sprites, namely multi-image files that are correctly displayed via CSS classes thatdefine offsets. Sprites, however, don't help much when images of different sizes and characteristics (e.g., color depth) are required in the page.

The data URI scheme (also known as the "data" URL scheme) offers an alternative to linking to an image as an external resource. I will discuss the dataURI scheme as defined in the Internet Engineering Task Force (IETF) Request for Comments (RFC) 2397 proposal and its prosand cons and show a sample implementation in the context of ASP.NET MVC applications.

Referencing Images in Web Pages

Dealing with images in web pages has never been difficult. In most cases, all you need is markup like the following example:

<img src="jerrylee.jpg" />

The markup ends up displaying an image; the image is taken from the specified URL and thus requires a separate download and an additional HTTP request.The URL doesn't have to point necessarily to a physical image file; it can reference any endpoint that can return a content type compatible with thebrowser's expectations for the tag. For example, the URL can be an HTTP handler or a controller action method that returns an image content type. Ifthe URL can't return a valid content item, or the request ends with an HTTP 404 Not Found error, then the browser displays a default icon. Figure 1 shows another, more flexible way of referencing images that displays your placeholder image when the requested one can't be displayed.

The subsequent URL you reference in the <img> element is the following:

<img src="/image/download/img="~/images/notanimage.jpg" />

The result is that if the requested image is missing, the specified image is served instead. In the example, the default missing image is decided bythe controller method; however, you can change that by adding another parameter to the query string:

<img src="/image/download/img="~/images/notanimage.jpg&defaultimg=your_missing_img.jpg" />

A common scenario is when you need to retrieve the image from a database. Also in this case, you resort to an HTTP handler (in Web Forms) or an ad hoccontroller (in ASP.NET MVC) that makes the query, gets the bits, and streams them out to the browser by using a different overload of the File methodthat accepts an array of bytes.

When it comes to image display in web pages, there's another possibility that is gaining popularity, especially for its use in the development ofmobile pages: passing the <img> element just the source bytes of the image. The data URI scheme serves just this purpose.

The Data URI Scheme

The data URI scheme defines a standard for embedding relatively small pieces of data within the page instead of linking the data as an externalresource. The net effect of applying the data URI scheme is that the content of the src attribute of the <img> element matches the followingtemplate:

data:[<content-type>][;base64],<bytes of the image>

First, you place the data keyword followed by the MIME type of the image. Next, you place the Base64 keyword followed by the Base64-encodedrepresentation of the binary image. If you were embedding an image manually, here's the markup you would need:

<img class="image" src="data:image/jpg;base64,/9j/4AAQSkZJRgA..." alt="" />

This manual approach is not even affordable for a one-pixel image. A 1x1 JPEG image, in fact, is about 600 bytes, which increases to 800 when youencode to Base64. You don't want to cut and paste all that human-unreadable text; in addition, you don't want to replace it every time you edit orreplace the image.

So in Web Forms, you would probably create a custom server control to emit an appropriate <img> tag with programmatically calculated image data.In ASP.NET MVC, more simply, you would create a URL extension method that takes an image URL and returns an encoded string.

A Helper Method for Inline Images

I see two ways to approach the task of creating a helper method for inline images. You can create an HTML helper that returns the full <img>element, taking into account the various attributes such as alt, class, width, and the like. Not a big deal actually; you just take the signature of anexisting HTML helper and stick to that. In doing so, you can also integrate in the helper the logic to check whether the requested image really existsand return a given placeholder otherwise.

I prefer to go with an extension method that takes the image URL (and possibly the URL to use in case of a not-found exception) and returns the text toembed, formatted according to the data URI scheme. Let's call this method InlineImage, and let's define it as an extension method for the UrlHelperclass. Here's how you end up using it in an ASP.NET MVC view:

<img class="image" src="@Url.InlineImage("~/Images/OnePixel.jpg")" alt="" />

Figure 2 shows the full source code of the extension method.

It should be noted that the code in Figure 2 defaults to JPEG as the content type. You might want to add that information as an extra parameter to themethod, or you can find a way to programmatically detect the type of the image being used. Figure 3 shows a comprehensive page that references imagesin a variety of ways; Figure 4 shows the HTML image references for that page.

Figure 3: Inline images

Figure 4: HTML image references for page shown in Figure 3

<img class="image" src="@Url.Content("~/Images/GermanShep.jpg")" alt="" /><img class="image" src="@Url.Content("~/Images/Square.jpg")" alt="" /><img class="image" src="@Url.InlineImage("~/Images/Square.jpg")" alt="" /><img class="image" src="@Url.InlineImage("~/Images/OnePixel.jpg")" alt="" /><img class="image" src="@Url.Content("~/image/download?img=~/Images/NotAnImage.jpg")" alt="" />


 You can also use the data URI scheme within a CSS file. The following code, in fact, works as well.


body {  background:url(data:image/gif;base64,AAazToeHh0...);}

The problem is that you can't use helpers in a CSS file to keep the code maintainable. It seems that the only alternative is producing the CSS filewith a call to some sort of preprocessor that expands images inline and serves the browser a valid style sheet.

Data URI Scheme and Browsers

The data URI scheme is not a feature that every browser supports. However, you'll find the data URI scheme supported in nearly all top-level andpopular browsers used today. It doesn't work with Internet Explorer prior to version 8, but it works with most recent versions of Opera, Firefox,Chrome, and Safari. Also notice that browsers typically limit the size of images they support inline. This limit typically varies from 32KB to 100KB;thus, the data URI scheme is appropriate for relatively small images that are consistent with the graphics of the website.

From a caching standpoint, browsers don't treat inline images the same way that they treat linked images. Inline images are not recognized as distinctresources and are subsequently not cached independently. Inline images are treated as a constituent part of the page, and their content is downloadedover and over again whenever the page is refreshed.

If you consider that an ASPX page is deemed a dynamic resource and is re-downloaded every time, you might well question the benefits of using the dataURI scheme. On one hand, inline images reduce the number of HTTP requests and increase the browser's bandwidth by saving a concurrent call to the samehost. Browsers, in fact, are limited to a few concurrent calls to the same host; in this way, you save one request, thus adding another point to theoptimization strategy. Having said that, however, what's really the point of using the data URI scheme? Let's find out.

Scenarios for Inline Images

Recently, I wanted to try a mobile site on a relatively middle-end device based on an HTML browser with CSS capabilities and no Ajax and DOMmanipulation support. Clearly, the processing power of the device was also quite limited, and it could only connect over a 3G data network -- no Wi-Fi.Well, the skeleton of the page displayed quite quickly, but it took ages to have the web page finalized -- that is, with all images and styleinformation fully processed. You could see clearly that multiple requests were made and how this affected page load time and rendering. When I embeddedboth CSS and images in the same page, the download process probably took longer, but the rendering was smooth and the user experience incomparablybetter than if the images had not been embedded inline.

What's the bottom line? The data URI scheme is particularly important for mobile sites. In mobile site development, you need to make the downloadhighly efficient while optimizing the user experience. Also consider that for mobile sites, reducing the number of HTTP requests also has a positiveeffect on the device battery's life.

A Useful Scheme for Certain Scenarios

It is commonly accepted that reducing the number of HTTP requests improves the load time of pages and the user experience. Combining the use of scriptsand CSS style sheets is a known trick for reducing HTTP requests, as is creating image sprites. Image sprites work well when images are contiguous andnearly the same size. However, when you have images of multiple sizes and varying characteristics on a page, consider using the data URI scheme tooptimize both page rendering and user experience -- especially for mobile websites.

Dino Esposito, author of Programming Microsoft ASP.NET 4 and Programming Microsoft ASP.NET MVC (Microsoft Press), is a trainer and consultantspecializing in web and mobile architectures and effective code design principles and practices. Follow Dino on Twitter: @despos.

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like