2

ASP.NET MVC4 application MVC4 buildit bundling and minification is used. Application should work also in offline.

I tried to create manifest using code below but this does not work since v= parameters will change if source code is changed. How to create manifest which works without manually changing bundle query string parameters if bundling and minification are used?

<!DOCTYPE html>
<html manifest="~/Sale/Manifest">

<head>

    @Erp.Helpers.Bundles.Render("~/css/pos", new { media = "screen" })
    @Erp.Helpers.Bundles.Render("~/css/receipt", new { media = "print" })
    @Scripts.Render("~/pos.js")
</head>

controller:

public ContentResult Manifest()
        {
            return new ContentResult()
            {
                Content = @"CACHE MANIFEST
CACHE:
pos?v=esdw2223023094323
css/pos?v=ewe3334324r33432343
css/receipt?v=w333543334324r33432343

NETWORK:
*
"
   };
}

C# Web.Optimization Bundles and HTML5 cache Manifest contains similar question without answer.

Update

I tried answers but got error in chrome console

Application Cache Error event: Resource fetch failed (404) http://localhost:52216/erp/Sale/pos.js 

Application is running using

        BundleTable.EnableOptimizations = true;

and in debug mode by pressing F5 from VSE 2013 for Web

I tried suggestions in answers using

public class SaleController : ControllerBase
{

    public ContentResult Manifest()
    {
        return new ContentResult()
        {
            Content = string.Format(@"CACHE MANIFEST
CACHE:
   {0}
   {1}
   {2}
", 
Scripts.Url("pos.js"),  // tried also Scripts.Url("pos")
Styles.Url("css/pos"),
Styles.Url("css/receipt")),

... in controller.

view source in browser shows

<html manifest="/erp/Sale/Manifest">
<head>
  <link href="/erp/css/pos?v=sN8iz_u3gRGE6MQKGq6KocU-SUIUMcQxKVuESa_L2l41" rel="stylesheet" media="screen"/>
    <link href="/erp/css/receipt?v=C6qCUe6W1VM6yxNe-RgZRY9R0Gws1vU0lMuoKIn1uVE1" rel="stylesheet" media="print"/>
    <script src="/erp/pos.js?v=a-TsureIIlzxwhaItWMV7Ajfw-YXE3x6hUld3cxwAqI1"></script>

generated manifest contains

CACHE MANIFEST
CACHE:
/erp/Sale/pos.js
/erp/Sale/css/pos
/erp/Sale/css/receipt

How to fix this ? It looks like invalid urls are generated to manifest:

  1. Sale directory is added
  2. Query string is not present
Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378

3 Answers3

4

There are methods on the Styles and Scripts objects in System.Web.Optimization that will give you the URL of the resource.

You can call Scripts.Url(string) to give you the URL of the script file, complete with the hash. You can also call Styles.Url(string) to give you the URL of the style sheet, complete with the hash.

using System.Web.Optimization;
using System.Web.Mvc;

namespace StackOverflow.Controllers
{
    public class StackOverflowController : Controller
    {
        public ContentResult Manifest()
        {
            return new ContentResult()
            {
                Content = string.Format( 
@"CACHE MANIFEST
CACHE:
{0}
{1}
{2}

NETWORK:
*
",
 Scripts.Url("~/pos.js"),
 Styles.Url("~/css/pos"),
 Styles.Url("~/css/receipt"))
            };
        }
    }
}

The cache-busting hashes will only be added when the site is run with <compilation debug="false" /> specified in the web.config file.

Pervez Choudhury
  • 2,892
  • 3
  • 27
  • 28
  • Thank you. This sample does not use full bundle name. Should `~/pos.js` used instead of `pos` ? In debug mode bundling is turned off and multiple files are referenced. How to make this work automatically without bundling also ? – Andrus Dec 16 '13 at 10:39
  • Pervez Choudhury: I tried this but got manifest fetch error. I updated question. How to fix ? – Andrus Dec 16 '13 at 11:05
  • @Andrus - I've added the relative urls to the code and added a note about when the query string parameters are visible. – Pervez Choudhury Dec 16 '13 at 14:13
  • Bundle contains many css and js files. Your solution renders only single file so it will not work in debug mode. Should I use solution from http://kazimanzurrashid.com/posts/html5-offline-cache-integration-with-asp-dot-net-mvc-bundle ? It looks like this work in debug mode also is it so ? – Andrus Dec 17 '13 at 10:52
1

Scripts.Url gives you the URL for the bundle, without rendering out the script tags. Does that answer your question?

samjudson
  • 56,243
  • 7
  • 59
  • 69
  • I triedt this but got manifest fetch error. I updated question. How to fix ? – Andrus Dec 16 '13 at 11:06
  • You pass the same thing into Scripts.Url as you do to Scripts.Render - i.e. the name of your bundle. In the above you have "~/pos.js" as the name of your bundle. – samjudson Dec 16 '13 at 12:43
0

You can use Scripts.RenderFormat or Styles.RenderFormat to render the full list of files when run with debug="true" and only the minified version when run with debug="false".

Here's an example:

    public ActionResult AppManifest()
    {
        string cacheFiles = "";

        cacheFiles = Scripts.RenderFormat("{0}",
            "~/bundles/jquery",
            "~/bundles/jqueryval",
            "~/bundles/bootstrap").ToString();

        cacheFiles += Styles.RenderFormat("{0}",
            "~/Content/css");

        string manifest = String.Format(@"CACHE MANIFEST

  CACHE:
  {0}", cacheFiles);

        return Content(manifest, "text/cache-manifest");
    }
Hugo
  • 122
  • 1
  • 8