The goal of this blog entry is to describe how you can create HTML5
Offline Web Applications when building ASP.NET web applications. I
describe the method that I used to create an offline Web application
when building the
JavaScript Reference application.
You can read about the HTML5 Offline Web Application standard by visiting the following links:
Currently,
the HTML5 Offline Web Applications feature works with all modern
browsers with one important exception. You can use Offline Web
Applications with Firefox, Chrome, and Safari (including iPhone Safari).
Unfortunately, however, Internet Explorer does not support Offline Web
Applications (not even IE 9).
Why Build an HTML5 Offline Web Application?
The
official reason to build an Offline Web Application is so that you do
not need to be connected to the Internet to use it. For example, you can
use the JavaScript Reference Application when flying in an airplane,
riding a subway, or hiding in a cave in Borneo.
The JavaScript
Reference Application works great on my iPhone even when I am completely
disconnected from any network. The following screenshot shows the
JavaScript Reference Application running on my iPhone when airplane mode
is enabled (notice the little orange airplane):
Admittedly, it is becoming increasingly difficult to find locations where you can’t get Internet access.
A
second, and possibly better, reason to create Offline Web Applications
is speed. An Offline Web Application must be downloaded only once. After
it gets downloaded, all of the files required by your Web application
(HTML, CSS, JavaScript, Image) are stored persistently on your computer.
Think of Offline Web Applications as providing you with a
super browser cache. Normally, when you cache files in a browser, the
files are cached on a file-by-file basis. For each HTML, CSS, image, or
JavaScript file, you specify how long the file should remain in the
cache by setting cache headers.
Unlike the normal browser
caching mechanism, the HTML5 Offline Web Application cache is used to
specify a caching policy for an entire set of files. You use a manifest
file to list the files that you want to cache and these files are cached
until the manifest is changed.
Another advantage of using the
HTML5 offline cache is that the HTML5 standard supports several
JavaScript events and methods related to the offline cache. For example,
you can be notified in your JavaScript code whenever the offline
application has been updated. You can use JavaScript methods, such as
the ApplicationCache.update() method, to update the cache
programmatically.
Creating the Manifest File
The HTML5
Offline Cache uses a manifest file to determine the files that get
cached. Here’s what the manifest file looks like for the JavaScript
Reference application:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
CACHE MANIFEST
# v30
Default.aspx
# Standard Script Libraries
Scripts/jquery-1.4.4.min.js
Scripts/jquery-ui-1.8.7.custom.min.js
Scripts/jquery.tmpl.min.js
Scripts/json2.js
# App Scripts
App_Scripts/combine.js
App_Scripts/combine.debug.js
# Content (CSS & images)
Content/ default .css
Content/logo.png
Content/ui-lightness/jquery-ui-1.8.7.custom.css
Content/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png
Content/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png
Content/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
Content/ui-lightness/images/ui-icons_222222_256x240.png
Content/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png
Content/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png
Content/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png
Content/ui-lightness/images/ui-icons_ffffff_256x240.png
Content/ui-lightness/images/ui-icons_ef8c08_256x240.png
Content/browsers/c8.png
Content/browsers/es3.png
Content/browsers/es5.png
Content/browsers/ff3_6.png
Content/browsers/ie8.png
Content/browsers/ie9.png
Content/browsers/sf5.png
NETWORK:
Services/EntryService.svc
http:
|
A Cache Manifest file always starts with the line of text
Cache Manifest.
In the manifest above, all of the CSS, image, and JavaScript files
required by the JavaScript Reference application are listed. For
example, the Default.aspx ASP.NET page, jQuery library, JQuery UI
library, and several images are listed.
Notice that you can add comments to a manifest by starting a line
with the hash character (#). I use comments in the manifest above to
group JavaScript and image files.
Finally, notice that there is a NETWORK: section of the manifest. You
list any file that you do not want to cache (any file that requires
network access) in this section. In the manifest above, the NETWORK:
section includes the URL for a WCF Service named EntryService.svc. This
service is called to get the JavaScript entries displayed by the
JavaScript Reference.
There are two important things that you need to be aware of when
using a manifest file. First, all relative URLs listed in a manifest are
resolved relative to the manifest file. The URLs listed in the manifest
above are all resolved relative to the root of the application because
the manifest file is located in the application root.
Second, whenever you make a change to the manifest file, browsers
will download all of the files contained in the manifest (all of them).
For example, if you add a new file to the manifest then any browser that
supports the Offline Cache standard will detect the change in the
manifest and download all of the files listed in the manifest
automatically.
If you make changes to files in the manifest (for example, modify a
JavaScript file) then you need to make a change in the manifest file in
order for the new version of the file to be downloaded. The standard way
of updating a manifest file is to include a comment with a version
number. The manifest above includes a # v30 comment. If you make a
change to a file then you need to modify the comment to be # v31 in
order for the new file to be downloaded.
When Are Updated Files Downloaded?
When you make changes to a manifest, the changes are not reflected
the very next time you open the offline application in your web browser.
Your web browser will download the updated files in the background.
This can be very confusing when you are working with JavaScript
files. If you make a change to a JavaScript file, and you have cached
the application offline, then the changes to the JavaScript file won’t
appear when you reload the application.
The HTML5 standard includes new JavaScript events and methods that
you can use to track changes and make changes to the Application Cache.
You can use the ApplicationCache.update() method to initiate an update
to the application cache and you can use the
ApplicationCache.swapCache() method to switch to the latest version of a
cached application.
My heartfelt recommendation is that you do not enable your
application for offline storage until after you finish writing your
application code. Otherwise, debugging the application can become a very
confusing experience.
Offline Web Applications versus Local Storage
Be careful to not confuse the HTML5 Offline Web Application feature
and HTML5 Local Storage (aka DOM storage) feature. The JavaScript
Reference Application uses both features.
HTML5 Local Storage enables you to store key/value pairs
persistently. Think of Local Storage as a super cookie. I describe how
the JavaScript Reference Application uses Local Storage to store the
database of JavaScript entries in a
separate blog entry.
Offline Web Applications enable you to store static files persistently. Think of Offline Web Applications as a super cache.
Creating a Manifest File in an ASP.NET Application
A manifest file must be served with the MIME type
text/cache-manifest. In order to serve the JavaScript Reference manifest
with the proper MIME type, I added two files to the JavaScript
Reference Application project:
- Manifest.txt – This text file contains the actual manifest file.
- Manifest.ashx – This generic handler sends the Manifest.txt file with the MIME type text/cache-manifest.
Here’s the code for the generic handler:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
using System.Web;
namespace JavaScriptReference {
public class Manifest : IHttpHandler {
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = "text/cache-manifest" ;
context.Response.WriteFile(context.Server.MapPath( "Manifest.txt" ));
}
public bool IsReusable {
get {
return false ;
}
}
}
}
|
The Default.aspx file contains a reference to the manifest. The opening HTML tag in the Default.aspx file looks like this:
<html xmlns="http://www.w3.org/1999/xhtml" manifest="Manifest.ashx">
Notice that the HTML tag contains a manifest attribute that points to
the Manifest.ashx generic handler. Internet Explorer simply ignores
this attribute. Every other modern browser will download the manifest
when the Default.aspx page is requested.
Seeing the Offline Web Application in Action
The experience of using an HTML5 Web Application is different with
different browsers. When you first open the JavaScript Reference
application with Firefox, you get the following warning:

Notice that you are provided with the choice of whether you want to
use the application offline or not. Browsers other than Firefox, such as
Chrome and Safari, do not provide you with this choice. Chrome and
Safari will create an offline cache automatically.
If you click the Allow button then Firefox will download all of the
files listed in the manifest. You can view the files contained in the
Firefox offline application cache by typing about:cache in the Firefox
address bar:

You can view the actual items being cached by clicking the List Cache Entries link:

The Offline Web Application experience is different in the case of
Google Chrome. You can view the entries in the offline cache by opening
the Developer Tools (hit Shift+CTRL+I), selecting the Storage tab, and
selecting Application Cache:

Notice that you view the status of the Application Cache. In the
screen shot above, the status is UNCACHED which means that the files
listed in the manifest have not been downloaded and cached yet. The
different possible values for the status are included in the
HTML5 Offline Web Application standard:
- UNCACHED – The Application Cache has not been initialized.
- IDLE – The Application Cache is not currently being updated.
- CHECKING – The Application Cache is being fetched and checked for updates.
- DOWNLOADING – The files in the Application Cache are being updated.
- UPDATEREADY – There is a new version of the Application.
- OBSOLETE – The contents of the Application Cache are obsolete.
Summary
In this blog entry, I provided a description of how you can use the
HTML5 Offline Web Application feature in the context of an ASP.NET
application. I described how this feature is used with the JavaScript
Reference Application to store the entire application on a user’s
computer.
By taking advantage of this new feature of the HTML5 standard, you
can improve the performance of your ASP.NET web applications by
requiring users of your web application to download your application
once and only once. Furthermore, you can enable users to take advantage
of your applications anywhere -- regardless of whether or not they are
connected to the Internet.
If you liked this blog post then please
Subscribe
to this blog or
Kick It
for DotNetKicks.