Skip navigation

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

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

Images have always been linked to websites as external resources. The HTML tag offers the src attribute for you to indicate the URL from which the browser can download the desired image. Depending on the settings, the image may then be cached locally to save you additional downloads when the 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 only possible 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 is commonly applied to script and Cascading Style Sheets (CSS) files, which are sometimes merged into a single file when not embedded as plain text in the page. Optimizing the download of images typically means creating sprites, namely multi-image files that are correctly displayed via CSS classes that define 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 data URI scheme as defined in the Internet Engineering Task Force (IETF) Request for Comments (RFC) 2397 proposal and its pros and 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:

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 the browser'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. If the 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 element is the following:



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 by the controller method; however, you can change that by adding another parameter to the query string:

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 hoc controller (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 method that 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 of mobile pages: passing the 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 external resource. The net effect of applying the data URI scheme is that the content of the src attribute of the element matches the following template:

data:[][;base64],

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

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 you encode 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 or replace the image.

So in Web Forms, you would probably create a custom server control to emit an appropriate 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 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 an existing 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 exists and 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 to embed, formatted according to the data URI scheme. Let's call this method InlineImage, and let's define it as an extension method for the UrlHelper class. Here's how you end up using it in an ASP.NET MVC view:

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 the method, or you can find a way to programmatically detect the type of the image being used. Figure 3 shows a comprehensive page that references images in a variety of ways; Figure 4 shows the HTML image references for that page.

140971_fig3_inline_images
Figure 3: Inline images



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





 

 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 file with 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 and popular 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 distinct resources and are subsequently not cached independently. Inline images are treated as a constituent part of the page, and their content is downloaded over 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 data URI 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 same host. 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 the optimization 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 DOM manipulation 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 style information fully processed. You could see clearly that multiple requests were made and how this affected page load time and rendering. When I embedded both CSS and images in the same page, the download process probably took longer, but the rendering was smooth and the user experience incomparably better 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 download highly efficient while optimizing the user experience. Also consider that for mobile sites, reducing the number of HTTP requests also has a positive effect 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 scripts and CSS style sheets is a known trick for reducing HTTP requests, as is creating image sprites. Image sprites work well when images are contiguous and nearly the same size. However, when you have images of multiple sizes and varying characteristics on a page, consider using the data URI scheme to optimize 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 consultant specializing in web and mobile architectures and effective code design principles and practices. Follow Dino on Twitter: @despos.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish