In this article, I will explain how you can create an Offline Web Application using ASP.NET MVC 5, HTML 5 Application Cache API using Cache Manifest file to define the contents to be cached and JQuery.

Source Code : Complete source code for article can be found on Github repo https://github.com/sudipta-chaudhari/HTML5_AppCache_MVC5

Tools used : Visual Studio 2017

Technologies used : ASP.NET MVC 5, HTML5 Application Cache API, JQuery, Bootstrap

Key Terms : Application Cache, Cache Manifest file, navigator.onLine()

As most of us are well versed in creating web apps which work great when user is online.

Consider a scenario where a user while filling a form with multiple fields and lastly clicks Submit button. User suddenly finds that a “Server not found” message in Firefox, “You’re not connected” message in IE or “There is no Internet connection” message or something similar is displayed all the form data filled by the user is lost and user is left with no choice than to fill in the form again or when the page is refreshed data is lost. This can happen as user lost internet connectivity intermittently or there was some temporary problem with the server or while user is on move and using a mobile or tablet device and in a place such as boarding a flight or in a train where there is no internet connectivity.

In such cases, the online web applications fail. To make the web apps work offline, the web app needs to cache/download the primary site content pages, images, CSS, Java scripts etc while can be used offline. Browser doesn’t need to wait for assets and data to be loaded from the server instead can use the cached assets and data.

Let’s see the real action how to achieve offline web application functionality. I will show you how Offline feature can be achieved using HTML5 Application Cache API using a cache manifest file. I will come to this as we build the project as per the step by step instructions listed below.

Step (1) : Create ASP.NET MVC 5 application

Create a new ASP.NET MVC 5 web application in Visual Studio 2017.

The default Razor Views for home, ‘Home\Index.cshtml‘ and ‘Shared\_Layout.cshtml‘ the shared layout view serving as the master page will be created by default.

Add a new Razor view named ‘About‘ to the project.

Step (2) : Add Style & Script Bundles in Shared Layout page

Edit ‘Shared\_Layout.cshtml’ view and in the head section, include the site’s CSS and Javascript files for JQuery and Modernizr as below.

@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/modernizr")

Remove the below code from bottom of the page before the closing of body tag.

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)

Step (3) : Create MVC Style & Script Bundles

Create Style and Script Bundles for the above three items in the ‘AppStart\BundleConfig.cs‘ file’s RegisterBundles method as shown below:

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                "~/Scripts/jquery-{version}.js"));

    bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                "~/Scripts/modernizr-*"));

    bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
              "~/Scripts/bootstrap.js",
              "~/Scripts/respond.js"));

    bundles.Add(new StyleBundle("~/Content/css").Include(
              "~/Content/bootstrap.css",
              "~/Content/site.css",
              "~/Content/Style.css"));
}

Step (4) : Create Stylesheet

Add new style sheet named ‘Style.css’ under root ‘Content‘ folder. Add the below three classes to it

#onlineStatus {
    font-size: 1em;
    padding: 6px;
    -moz-border-radius-bottomleft: 10px;
    border-bottom-left-radius: 10px;
    color: #fff;
}

.online {
    background-color: #060;
}

.offline {
    background-color: #900;
}

Step (5) : Create JQuery scripts

Go to ‘Views\Shared\_Layout.cshtml‘ file and add JQuery document ready function. Under this section, create a JS function named ‘isOnline()‘ which checks the ‘navigator.onLine‘ property.

It returns the online status of the browser. The property returns a boolean value, with truemeaning online and false meaning offline. The property sends updates whenever the browser’s ability to connect to the network changes. The update occurs when the user follows links or when a script requests a remote page. For example, the property should return false when users click links soon after they lose internet connection.

Next create a div above @RenderBody section as shown below.

<div id="onlineStatus"></div>

This div will be used to display Online/Offline status.

Now create a JS function named reportOnlineStatus() as below which will be used to display Online/Offline status in the above div (onlineStatus)

function reportOnlineStatus() {
    var status = $("#onlineStatus");

    if (isOnLine()) {
        status.text("Online");
        status.
            removeClass("offline").
            addClass("online");
    }
    else {
        status.text("Offline");
        status.
            removeClass("online").
            addClass("offline");
    }
}

The above JS function inserts in the text in the ‘onlineStatus’ div as ‘Online’ with Green colored background or ‘Offline’ with ‘Red’ colored background as per browser’s Online or Offline status. As this div is placed on the shared layout page, the browser status will be displayed consistently on top of all views/pages.

Next, add the below window event listeners as shown below which listen to the browser’s Online/Offline and call out ‘reportOnlineStatus()‘ function created above.

window.addEventListener("online", function (e) {
    reportOnlineStatus();
}, true);

window.addEventListener("offline", function (e) {
    reportOnlineStatus();
}, true);

reportOnlineStatus();

After this, call the reportOnlineStatus() function to execute it as shown in last line of above code snippet.

Step (6) : Create Cache Manifest File

This is the step where I will show you how to create the Application Cache Manifest file and enable caching.

At the application root, create a new file named manifest.appcache as shown below.

CACHE MANIFEST
# version 1

CACHE:

/Content/bootstrap.css
/Content/Site.css
/Content/Style.css

/Scripts/jquery-1.10.2.js
/Scripts/bootstrap.js
/Scripts/modernizr-2.6.2.js
/Scripts/respond.js

/home
/home/index

NETWORK:
*

The first line of any application manifest file must read CACHE MANIFEST.

Lines starting with a ‘#’ are comment lines, but can also serve another purpose. An application’s cache is only updated when its manifest file changes. So for example, if you edit an image resource or change a JavaScript function, those changes will not be re-cached. You must modify the manifest file itself to inform the browser to refresh cached files.

Add a comment for version and keep changing the version number as and when there is a change in the resources.

The next section is the CACHE: section. The heading of CACHE: is optional. Files listed in the CACHE section may include any files regularly found as a part of a web application. You may reference any application files in the manifest. In this context, “application files” include static HTML pages, CSS files, images and scripts as well as server processed pages or files. The manifest only cares about the resulting file as served to the browser.

NETWORK: Resources that can be accessed only during online and should never be cached are listed under this section. An asterisk in the network section indicates that all the resources except for those mentioned in the CACHE MANIFEST section can be accessed only while online.

In the above cache manifest file, following items have been cached:-

(a) CSS Files
(b) JS Files
(c) MVC application route for the home view/page

MVC view created in Step (1) named “About” hasn’t been included it in the above cache manifest to show how the cached and non cached views/pages work.

Step (7) : Add MIME Type for Cache Manifest

Add the MIME extensions of ‘text/cache-manifest‘ in web.config for the file extension .appcache to be recognized. Under section, add the following section:

<staticContent>
      <remove fileExtension=".appcache" />
      <mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" />
</staticContent>

Step (8) : Reference Cache Manifest file

Now as the cache manifest file is created, it needs to be linked to our web application so that our application can start caching the items defined in the cache manifest file.

Open ‘Views\Shared\_Layout.cshtml‘ file and in the html tag, add the cache manifest file as :
<html manifest="/manifest.appcache">

Step (9) : Add event handler to Swap Cache 

Add the below JS code in Shared _Layout.cshtml page:

window.applicationCache.onupdateready = function (e) {
    applicationCache.swapCache();
    window.location.reload();
}

This event handler is called when there has been an updated to an existing Application Cache. swapCache() method of the applicationCache object swaps and downloads and cached all resources mentioned in the cache manifest file.

Step (10) : Deploy WebApp on Azure

In this step, I will deploy the application and check the caching.  I will deploy the application on Azure WebApp. You can deploy the application on local IIS or on an on-premise IIS web server.

TESTING

I tested this on below browsers and found it working fine

  • Chrome (59)
  • MS Edge (40)
  • Safari (5.1.4)

Step (1) : After deployment on Azure, launch the web app while being Online and open the browser console. The application’s home page will be displayed with the Online status and browser console will display HTML 5 application cache events. In the below screenshot, you can see that the cache manifest is checked and contents specified in cache manifest are downloaded by browser.

html5_appcache_pg1

Step (2) : Navigate to ‘About‘ link from header menu. The About view/page would be displayed and as you can see, it doesn’t have the layout page as it’s parent. This is done purposely as I anted to show you this page won’t be cached as the layout page will be cached itself since the cache manifest has been linked in shared layout page.

HTML5_AppCache_Pg2

Step (3) : Now close the browser, disconnect network/internet. Open the application home page URL in he browser. You will see the application home page has been loaded and displays an ‘Offline’ status. The browser console displays the application has been loaded from cache. Browser console also displays a manifest fetch error which is absolutely normal as there is no network and browser is trying to fetch the cache manifest as per the cache events. Also favicon.ico is not fetched in offline mode as this wasn’t specified in the cache manifest file as an item to be cached.

HTML5_AppCache_Pg3

Step (4) : In network disconnected state, navigate to ‘About‘ view/page. You will see that the about page is not loaded as this view/page wasn’t provided in the cache manifest file to be cached.

HTML5_AppCache_Pg4

Step 5 : Make some change to the application files mentioned in the cache manifest file, redeploy the changes on web server, open the web app’s home page and view browser console. You will notice that as the file(s) have changed, the cache will the updated and files will be cached again by the browser and new cached files will be available again.

[NOTE] : At the time of writing this article, HTML 5 Application Cache API has been deprecated. A new promise based API is available which is Service Worker but this is still in experimental state and is currently not supported by browsers like IE11, MS Edge etc.

I hope you followed the article. If you have any comments, questions or suggestions, leave a message and I will try to respond at my earliest.

Advertisements