搜索
首页web前端H5教程使用ASP.NET MVC构建HTML5离线web应用程序

       web应用程序的主要制约之一就是连接性。在HTML5到来之前我们就曾想挖掘浏览器的能力,以使web应用程序能像桌面应用程序一样功能强大和易于使用,但浏览器始终让我们感到失望。虽然之前已出现了一些浏览器缓存技术,但这些缓存技术的设计初衷并不是为了使web应用程序能够完全地离线运行,令人遗憾的是,事实上使用这些技术的web应用程序很容易出问题,而且难于使用。HTML5试图通过离线应用程序缓存( offline application cache)技术来填补浏览器的能力空缺,该技术能更加可靠地使web应用程序离线工作。

       为什么web应用程序需要离线运行呢?

       老实讲,一般来说,桌面电脑的web应用程序即使能够完全离线运行也不能带来多大的好处,因为桌面电脑一般都是一直连线的。我特别期待看到的是,移动设备web应用程序能够从离线应用程序缓存技术得到多大的好处。

       在许多地方,移动电话普及率都在持续增长。如果能够自然地填补网络断线的鸿沟,移动设备浏览器中的web应用程序对用户来说就更加友好了。

       在一些特定场景中,使整个应用程序能够离线运行,意味着我们只需创建一个跨平台的浏览器解决方案,而不必创建多个内建应用程序。

       试想一下,一位销售员需要随时随地向她的顾客展示商品目录单。她可以使用任何她想要的电子设备,她首次浏览商品目录单时需要连线,之后便能够随时随地离线浏览。

       应用程序缓存技术并不只是在离线状态下才有用武之地。我们可以将应用程序缓存作为一个超级缓存,用于本地存储资源,这样可以加速应用程序启动。服务器上更新了的资源可以在后台线程重新加载,加载完成之后便替换掉本地旧的资源并更新到正在运行的应用程序上。这种方式非常适用于桌面电脑的重量级web应用程序。

       清单文件

       要使用应用程序缓存,你不需要编写大量代码。你可以在一个简单的文本文件中定义需要离线使用的资源,这个文件被称作清单(manifest)文件。

       清单文件格式

       一个简单的清单文件具有如下格式:

  1. CACHE MANIFEST
  2. # Version 1.0
  3. CACHE:
  4. /home/index
  5. /content/style.css
  6. /scripts/main.js
  7. NETWORK:
  8. /service/status
  9. FALLBACK:
  10. /logo.png /logo_offline.png
复制代码


       其中,你必须将CACHE MANIFEST 头放在清单文件的第一行。

       以数字符号#开头的行是注释行。这通常用于显式地修改清单文件以通知浏览器更新缓存。比如,在你更新了一张图片但没有修改图片的名称时,这种方式非常有用,因为浏览器并没有其他方式可以检测到服务器上的图片已被更新。

       接下来,清单文件包含了以下三节:CACHE,NETWORK以及FALLBACK。在CACHE节你可以指定需要缓存的资源。需要一直从服务器下载的资源(即使在断线的情况下)则在NETWORK中指定。如果有大量的资源需要一直从服务器下载,你可以在NETWORK节中使用通配字符(即一个星号*)表示。在FALLBACK节中,你可以指定在离线状态下可以使用的备用资源。

       清单文件的格式并不特别严格。以上介绍的几个部分可以是任意次序的,它们甚至可以在一个清单文件中多次使用。

       在清单文件中你可以使用相对路径或者绝对路径来定位资源。如果你使用相对路径,则必须以清单文件的位置作为参考来定位资源。

       引用清单文件

       要将清单文件绑定到应用程序,需要将manifest属性添加到html标签上。每个引用清单文件的页面自身默认会被缓存。然而,还是建议在清单文件中显示列出你想要缓存的资源。如果某个页面没有在清单文件中被指定,同时也不曾被在线浏览过,则在离线状态下无法访问到这个页面,因为浏览器无法知道页面是否存在于本地缓存中。

复制代码


       检查缓存状态

       使用应用程序缓存API,我们可以检查应用程序缓存的状态。使用window.applicationCache这个属性可以查询当前缓存的状态。该状态属性的值是一个介于0至5之间的数字,每个数字对应一个特定的缓存状态。

21.jpg


       你可以使用setInterval函数来快速显示状态变化。

  1. setInterval(function () {
  2.       console.log(window.applicationCache.status)
  3. }, 500);
复制代码


       事件处理

       除了检查缓存状态,我们还可以处理特定事件。

22.jpg


       缓存替换

       当新缓存下载完成之后,它并不会立即替换掉旧的缓存,而是直到我们通知应用程序使用新缓存时它才进行替换。我们可以通过处理updateready事件,使用swapCache将旧缓存替换为新缓存。更新的资源要在刷新页面后才能见到。

  1. window.applicationCache.onupdateready = function(){
  2.       window.applicationCache.swapCache();
  3. });
复制代码


       怎样让用户知道你的应用程序可以离线运行呢?

       据我所知,没有哪种浏览器会通知用户当前应用程序是能离线运行的。不过,我们可以自己通知用户:通过监听应用程序缓存的特定事件,当应用程序已经可以离线工作时通知用户。我们甚至可以将应用程序缓存生命周期的每个阶段都通知用户。

       应用程序缓存相关事件的处理是直截了当的。其中一个特别有用的事件是progress事件。每当一个资源下载完毕时这个事件被触发,其包含三个非常有用的属性,我们可以用这三个属性来显示下载进度:lengthComputable、loaded以及total。首先,我们需检查lengthComputable属性来判断loaded和total属性是否可用,接着我们使用loaded和total属性计算出资源下载的百分比进度。

  1. window.applicationCache.onchecking = function (e) {
  2.     updateCacheStatus('Checking for a new version of the application.');
  3. };
  4. window.applicationCache.ondownloading = function (e) {
  5.     updateCacheStatus('Downloading a new offline version of the application');
  6. };

  7. window.applicationCache.oncached = function (e) {
  8.     updateCacheStatus('The application is available offline.');
  9. };

  10. window.applicationCache.onerror = function (e) {
  11.     updateCacheStatus('Something went wrong while updating the offline version of the application. It will not be available offline.');
  12. };

  13. window.applicationCache.onupdateready = function (e) {
  14.     window.applicationCache.swapCache();
  15.     updateCacheStatus('The application was updated. Refresh for the changes to take place.');
  16. };

  17. window.applicationCache.onnoupdate = function (e) {
  18.     updateCacheStatus('The application is also available offline.');
  19. };

  20. window.applicationCache.onobsolete = function (e) {
  21.     updateCacheStatus('The application cannot be updated, no manifest file was found.');
  22. };

  23. window.applicationCache.onprogress = function (e) {
  24.     var message = 'Downloading offline resources.. ';
  25.     if (e.lengthComputable) {
  26.         updateCacheStatus(message + Math.round(e.loaded / e.total * 100) + '%');
  27.     } else {
  28.         updateCacheStatus(message);
  29.     };
  30. };
复制代码


       怎样检测浏览器是处于在线状态还是离线状态呢?

       你需要知道浏览器是在线的还是离线的有以下几个原因:也许是因为你想通知用户其正在离线工作,也许是因为你想在网络断开时禁用应用程序的某些功能,还或许是因为你想通过本地存储(local storage)技术以支持离线用户输入,然后在上线时将用户输入的文本同步到服务器。要实现这些需求,你可以通过自造基础架构,也可以通过使用开源项目或第三方项目。

       检测在线状态

       从原理上讲检测在线状态应该是非常简单的,比如在标准状况下,你使用navigator单件的onLine属性就可以检测出当前浏览器是否在线。

  1. console.log(navigator.onLine)
复制代码


       但事实上并非如此简单,因为各种浏览器对在线和离线的定义不尽相同。比如,旧版本的火狐浏览器只当用户显示地进行在线和离线状态切换时才更新onLine属性的值,而忽略了实际的网络状况。抛开实现上的不一致,检测网络连接状况本身就不是一件微不足道的事情。比如,假设你的电脑是连接上了的,但是你的路由器出问题了,这时应该显示什么状态呢?

       一种流行的hack方法是检查每个AJAX请求的状态码,然后当状态码为不成功时则回退到离线机制。

       事件处理

       如果你想在浏览器改变连线状态时做一些事情,你可以通过处理offline和online事件来实现。但是请注意,和检查onLine属性一样,使用这两个事件也有类似问题。

  1. window.addEventListener('offline', function(e) {
  2.   console.log('offline');
  3. }, false);
  4. window.addEventListener('online', function(e) {
  5.   alert('online');
  6. }, false);
复制代码


       浏览器支持

       除了Internet Explorer,所有主流现代浏览器都支持离线web应用程序。Internet Explorer 10也实现了相关规范,只是目前它还未发布。在caniuse.com上可以查看到每种浏览器及其版本对这一规范的支持情况。

       对于大部分实现,各主流浏览器基本上是相一致的。但在实现存储限额以及对限额的管理(这两项没有定义在规范中)上,各浏览器差异比较大。在测试你的web应用程序时应该考虑这个问题,移动设备中的浏览器在缓存大小上可是斤斤计较的。

       使用ASP.NET MVC生成和提供清单文件

       生成清单文件

       利用ASP.NET MVC创建和提供清单文件有几种方式。最简单地方式就是让ASP.NET MVC提供静态文本文件。然而,如果我们想要使用内建的ASP.NET MVC特性来解析路由,或者想编写代码来动态操控清单文件,我们最好使用自定义的action result。

       我把这个自定义的action result命名为ManifestResult,它继承自MVC框架中的FileResult类。提供清单文件服务时应该使用'text/cache-manifest' MIME类型,我把这个字符串传递给了父类的构造函数。

  1. public class ManifestResult : FileResult
  2. {
  3.     public ManifestResult(string version)
  4.         : base("text/cache-manifest") { }
  5. }
复制代码


       ManifestResult类具有四个属性,其中三个属性对应清单文件的三个节,另外一个属性对应版本号。表示CACHE节和NETWORK节的两个属性仅仅是字符串枚举,而表示FALLBACK节的属性是字典类型的,用于将资源映射到FALLBACK指定的资源。

  1. public class ManifestResult : FileResult
  2. {
  3.     public ManifestResult(string version)
  4.         : base("text/cache-manifest")
  5.     {
  6.             Version = version;
  7.         CacheResources = new List();
  8.         NetworkResources = new List();
  9.         FallbackResources = new Dictionary();
  10.     }
  11.     public string Version { get; set; }
  12.     public IEnumerable CacheResources { get; set; }
  13.     public IEnumerable NetworkResources { get; set; }
  14.     public Dictionary FallbackResources { get; set; }
  15. }
复制代码


       要将格式化的清单文件输出到响应流,需要重写WriteFile方法。

  1. protected override void WriteFile(HttpResponseBase response)
  2. {
  3. WriteManifestHeader(response);
  4.     WriteCacheResources(response);
  5.     WriteNetwork(response);
  6.     WriteFallback(response);
  7. }
  8. private void WriteManifestHeader(HttpResponseBase response)
  9. {
  10.     response.Output.WriteLine("CACHE MANIFEST");
  11.     response.Output.WriteLine("#V" + Version ?? string.Empty);
  12. }
  13. private void WriteCacheResources(HttpResponseBase response)
  14. {
  15.     response.Output.WriteLine("CACHE:");
  16.     foreach (var cacheResource in CacheResources)
  17.         response.Output.WriteLine(cacheResource);
  18. }
  19. private void WriteNetwork(HttpResponseBase response)
  20. {
  21.     response.Output.WriteLine();
  22.     response.Output.WriteLine("NETWORK:");
  23.     foreach (var networkResource in NetworkResources)
  24.         response.Output.WriteLine(networkResource);
  25. }
  26. private void WriteFallback(HttpResponseBase response)
  27. {
  28.     response.Output.WriteLine();
  29.     response.Output.WriteLine("FALLBACK:");
  30.     foreach (var fallbackResource in FallbackResources)
  31.         response.Output.WriteLine(fallbackResource.Key + " " + fallbackResource.Value);
  32. }
复制代码


       提供清单文件服务

       为了提供清单文件服务,我们要将相应的action添加到相应的控制器类中,以生成和返回清单文件的动作结果(action result)。在该action中,我们利用MVC的UrlHelper对象来正确地解析路由。

  1. public ActionResult Manifest()
  2. {
  3.      var manifestResult = new ManifestResult("1.0")
  4.     {
  5.          CacheResources = new List()
  6.              {
  7.                    Url.Action("Index", "Home"),
  8.                    "/content/style.css",
  9.                    "/scripts/main.js"
  10.              },
  11.              NetworkResources = new string[] { Url.Action("Status", "Service")},
  12.              FallbackResources = { { "/logo.png", "/logo_offline.png" } }
  13.     };
  14.     return manifestResult;
  15. }
复制代码


       为清单文件设置路由

       我们应该为清单文件设置特定的路由。大多数浏览器对清单文件的位置没有严格的规定,而最可靠的跨浏览器方式是将清单文件放在根目录,并将其命名为cache.manifest。在应用程序启动时,下面的代码将这个新的“cache.manifest”路由添加到路由表中。

  1. routes.MapRoute("cache.manifest", "cache.manifest", new { controller = "Resources", action = "Manifest" });
复制代码


       结论

       离线web应用程序是正处于不断发展中的HTML规范的重要内容之一。根据实际用例,你可能仅仅是利用这个特性来缓存资源或者让web应用程序完全离线运行。这个特性的中心就是清单文件。清单文件的格式和要求一点也不复杂,使用ASP.NET MVC或其他服务端技术可以直截了当地生成和提供清单文件服务。编写好清单文件之后,使用应用程序缓存API就可以很容易地进行缓存更新。你也可以使用这组API来查询缓存状态和处理应用程序缓存的特定事件。想知道浏览器处于在线状态还是离线状态,你可以通过检查navigator对象的onLine属性,或者处理特定的在线和离线事件来判断。


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何使用视口元标记来控制移动设备上的页面缩放?如何使用视口元标记来控制移动设备上的页面缩放?Mar 13, 2025 pm 08:00 PM

本文讨论了使用视口元标记来控制移动设备上的页面缩放,重点是宽度和初始尺度之类的设置,以获得最佳响应和性能。

如何使用HTML5和JavaScript创建互动游戏?如何使用HTML5和JavaScript创建互动游戏?Mar 10, 2025 pm 06:34 PM

本文使用JavaScript详细介绍了创建Interactive HTML5游戏。 它涵盖了游戏设计,HTML结构,CSS样式,JavaScript逻辑(包括事件处理和动画)以及音频集成。 必需的JavaScript库(Phaser,Pi

如何将音频添加到我的HTML5网站上?如何将音频添加到我的HTML5网站上?Mar 10, 2025 pm 03:01 PM

本文解释了如何使用< audio>元素,包括用于格式选择的最佳实践(MP3,OGG Vorbis),文件优化和JavaScript控件用于播放。 它强调使用多个音频f

如何使用地理位置API处理用户位置隐私和权限?如何使用地理位置API处理用户位置隐私和权限?Mar 18, 2025 pm 02:16 PM

本文讨论了使用GeOlocation API管理用户位置隐私和权限,并强调要求权限,确保数据安全性并遵守隐私法律的最佳实践。

如何将HTML5表单用于用户输入?如何将HTML5表单用于用户输入?Mar 10, 2025 pm 02:59 PM

本文解释了如何创建和验证HTML5表格。 它详细介绍了>元素,输入类型(文本,电子邮件,编号等)和属性(必需,模式,最小,最大)。 HTML5的优势比旧方法形成

如何使用HTML5页面可见性API检测页面何时可见?如何使用HTML5页面可见性API检测页面何时可见?Mar 13, 2025 pm 07:51 PM

本文讨论了使用HTML5页面可见性API来检测页面可见性,提高用户体验并优化资源使用情况。关键方面包括暂停媒体,减少CPU负载以及基于可见性变化管理分析。

如何将HTML5拖放API用于交互式用户界面?如何将HTML5拖放API用于交互式用户界面?Mar 18, 2025 pm 02:17 PM

本文介绍了如何使用HTML5拖放API来创建交互式用户界面,详细介绍了使元素可拖动的步骤,处理关键事件并通过自定义反馈来增强用户体验。它还讨论了一个常见的陷阱

如何使用HTML5 Websockets API进行客户端和服务器之间的双向通信?如何使用HTML5 Websockets API进行客户端和服务器之间的双向通信?Mar 12, 2025 pm 03:20 PM

本文解释了HTML5 Websockets API,用于实时双向客户服务器通信。 它详细详细介绍了客户端(JavaScript)和服务器端(Python/Flask)的实现,以应对可伸缩性,状态管理,一个挑战

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
2 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器