Friday, July 11, 2014

caching views which will never change in a mobile app

In the ASP.NET MVC Web API application I show of here, there is really only one view outside of the _Layout.cshtml "master page" and some partial views which I am pulling into the one full view by way of asynchronous JavaScript which reaches out to controllers like this one.

using System.Web.Mvc;
namespace Wallet.Controllers
{
   public class CreateWalletController : Controller
   {
      public ActionResult Index()
      {
         return PartialView();
      }
   }
}

 
 

Anyways... my "one full view" is the Index.cshtml file for the Index action of HomeController. It used to look like this:

<div id="view" class="view"></div>
<input type="hidden" value="@ViewBag.CurrentView" id="whereami" />
<script language="javascript">
   $(function() {
      getView();
   });
   function getView(currentView) {
      $("#view").html("");
      if (currentView) {
         $("#whereami").val(currentView);
      } else {
         currentView = $("#whereami").val();
      }
      $.ajax({
         type: "GET",
         url: "/" + currentView,
         data: 'html',
         success: function(result) {
            $("#view").html(result);
            adjustView();
         }
      });
   }
</script>

 
 

My plan was to fish out new partial views when "changing pages" within my application. Everything would happen by way of asynchronous JavaScript. Later on, I'd drive form submissions by way of the Web API. However, while there are some times when one HAS to speak back to the server, there might be other times when pulling up a new "page" requires no in-the-moment context. For example, the partial views for logging in and creating a new account would always look the same, no? Moreover, talking back to the server in a mobile scenario could be "expensive" due to connectivity concerns, so maybe it should only be done in-the-moment when absolutely necessarily. What if you have only one bar or you are dangerously using your cell phone while you drive and you go through the Eisenhower Tunnel on I-70? I thought it might be best to, after first loading the _Layout.cshtml "master page" HTML and then secondly loading the HTML for the first partial view for a "home page," start proactively trying to load the HTML for partials which may just be cached. I do just that in this revision to what is above:

<div id="view" class="view"></div>
<div id="viewcache" class="hide"></div>
<input type="hidden" value="@ViewBag.CurrentView" id="whereami" />
<input type="hidden" value="@ViewBag.Identity" id="whichami" />
<script language="javascript">
   $(function() {
      getView();
   });
   function getView(currentView, id) {
      $("#view").html("");
      if (currentView) {
         $("#whereami").val(currentView);
         if (id) {
            $("#whichami").val(id);
         } else {
            $("#whichami").val("");
         }
      } else {
         currentView = $("#whereami").val();
         id = $("#whichami").val();
      }
      var isAlreadyHoldingView = false;
      if (!id) {
         $('#viewcache').children().each(function() {
            if (this.id == currentView + "View") {
               $("#view").html($("#"+currentView+"View").html());
               isAlreadyHoldingView = true;
            }
         });
      }
      if (!isAlreadyHoldingView) {
         $.ajax({
            type: "GET",
            url: craftUrl(currentView, id),
            data: 'html',
            success: function (result) {
               $("#view").html(result);
               adjustView();
               if ($("#viewcache").html() == "") {
                  tryToCacheViews();
               }
            }
         });
      }
   }
   function craftUrl(currentView, id) {
      if (id) {
         return "/" + currentView + "/index/" + id;
      } else {
         return "/" + currentView;
      }
   }
   function tryToCacheViews() {
      var viewsToCache = ["SignIn", "CreateWallet"];
      for (var i = 0; i < viewsToCache.length; i++) {
         $.ajax({
            type: "GET",
            url: craftUrl(viewsToCache[i]),
            data: 'html',
            success: function (result) {
               $("#viewcache").append("<div id='" + this.url.split("?")[0].substring(1) + "View'>"
                     + result + "</div>");
            }
         });
      };
   }
</script>

 
 

At this year's Dallas Day of Dot Net conference I saw Chris Love give a talk on how he had built an HTML hybrid mobile app using jQuery back before a lot of the modern day JavaScript frameworks existed and he, in his application, tucked his views away to local storage. I suppose I could do that do. I thought I'd just tuck them into a hidden div all the same. I know this whole thing is sloppy. I'm experimenting.

 
 

Addendum 7/17/2014: My use of data instead of dataType in the jQuery .ajax implementation within this blog posting is inappropriate. I should have used dataType. Please see this.

No comments:

Post a Comment