MVC and the HTML5 Application Cache

HTML5 has loads of awesome features and recently I have been playing around with a feature called the Application Cache. The Application Cache is designed to allow you to run your web application offline - that is, without a network connection. A web browser that implements HTML5 offline applications will read the list of URLs from the manifest file, download the resources, cache them locally, and automatically keep the local copies up to date as they change. When you don't have a network connection, the browser will automatically switch over to the local copies instead. Most modern browsers offer support for the Application Cache this includes FIREFOX (3.5+), SAFARI (4.0+), CHROME (5.0+), OPERA (10.6+), IPHONE and ANDROID. Unfortunately, Internet Explorer doesn't currently offer support for Application Cache.

So...what if we could use the benefits of the Application Cache with an online application? The user could access all the resources that they need from the Application Cache instead of the server, and in turn the page would load a lot faster. Another added advantage of using the Application Cache is that there would be a reduced server load and the browser only needs to download anything new instead of fetching the resources that it already has.

Let's get started with the basics of using the Application Cache in an MVC project. In order to enable the Application Cache you need to include the manifest attribute on the HTML tag.

The manifest file can be located anywhere on your web server and contains a list of the things that you want to store in the Application Cache. You could always simply link to a static text file on your server, but I quite like to use the MVC ActionResult and View to return a dynamic manifest file. The browser will continue to use the cached version of the resources until the manifest file has changed or been updated. It can sometimes make debugging your application a nightmare, so if you are reloading your page and find that you are only seeing the cached version - you will need to make a change to the manifest file in order for the browser to fetch the new version.

Right, let's create our dynamic manifest page. Add a new method on your controller - I called mine "Manifest". Notice how the MVC route matches up to the manifest attribute link we supplied on the HTML tag.

Next, add a view for that ActionResult.

Close to the top of the View you will notice a ContentType of "text/cache-manifest". All manifest files must be served with a content type of text/cache-manifest. The manifest file also needs to begin with "CACHE MANIFEST" on the first line.

You should also notice that on that View there is a method called AppendHash(). Thanks to my colleague @ShirtlessKirk for coming up with this idea, this is the Ninja way of handling changing resources.

The method reads the resources and creates a Hash string based on the contents. This way the Hash Key only changes based on whether the resource has changed. This is then appended onto the end of the filename with a Querystring. The Hash Key will only change if the file has changed - this means no updating your manifest file every time a resource (CSS, Javascript, etc.) file has changed! I won't go into too much detail about the class and method that appends the Hash to the file URL, but the whole solution in this article is available for download here.

In order to see the Application Cache in action, let's fire up a browser. I quite like to test with Google Chrome, because the Developer Tools make it quite easy to see what's in the Application Cache. If you hit CTRL-SHIFT-J you should notice the Google Chrome Developer Tools appear. The first time a page loads with the manifest and Application Cache you will notice something like this appearing in the tools console:

As you can see it is downloading the resources that are in the manifest file. If you choose the RESOURCES tab, and then drill down to the Application Cache, you should notice something like this (notice the hash appended):

If we reload the page, all the resources will be loaded from the Application Cache and not be downloaded from the server. Check the Developer Tools console:

An important thing to keep in mind is that any pages that you add the manifest attribute to will be cached in the browser - this INCLUDES THE PAGE ITSELF! You can't just cache the resources and not the page - it's not really designed to work this way. So, the disadvantage of using the Application Cache is that it doesn't play too well with server side dynamic pages. If you think of a website, the pages that you would add to the Application Cache would normally be the pages that are static or pages that don't change that often. If you add the manifest attribute to your Master Page you will cache your entire application and not notice any changes when refreshing - Instead consider only adding this to pages that aren't updated regularly.

For more information on the HTML5 Application Cache, please take a look at this website. If you would like to download the example solution used in this article, please download it here.