How to force BundleCollection to flush cached script bundles in MVC4

We hear your pain on documentation, unfortunately this feature is still changing quite fast, and generating documentation has some lag, and can be outdated almost immediately. Rick's blog post is up to date, and I've tried to answer questions here as well to spread current info in the meantime. We are currently in the process of setting up our official codeplex site which will have always current documentation.

Now in regards to your specific issue of how to flush bundles form the cache.

  1. We store the bundled response inside of the ASP.NET cache using a key generated off of the bundle url requested, i.e. Context.Cache["System.Web.Optimization.Bundle:~/bundles/jquery"] we also setup cache dependencies against all of the files and directories that were used to generate this bundle. So if any of the underlying files or directories change, the cache entry will get flushed.

  2. We don't really support live updating of the BundleTable/BundleCollection on a per request basis. The fully supported scenario is that bundles are configured during app start(this is so everything works properly in the web farm scenario, otherwise some bundle requests would end up being 404's if sent to the wrong server). Looking at your code example, my guess is that you are trying to modify the bundle collection dynamically on a particular request? Any kind of bundle administration/reconfiguration should be accompanied by an appdomain reset to guarantee everything has been setup correctly.

So avoid modifying your bundle definitions without recycling your app domain. You are free to modify the actual files inside of your bundles, that should automatically be detected and generate new hashcodes for your bundle urls.


I've got a similar problem.
In my class BundleConfig I was trying to see what was the effect of using BundleTable.EnableOptimizations = true.

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        BundleTable.EnableOptimizations = true;

        bundles.Add(...);
    }
}

Everything was working fine.
At some point I was doing some debugging and set the property to false.
I struggled to understand what was happening cause it seemed that the bundle for jquery (the first one) wouldn't be resolved and loaded (/bundles/jquery?v=).

After some swearing I think(?!) I've managed to sort things out. Try to add bundles.Clear() and bundles.ResetAll() at the beginning of the registration and things should start to work again.

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Clear();
        bundles.ResetAll();

        BundleTable.EnableOptimizations = false;

        bundles.Add(...);
    }
}

I've realized I need to run these two methods only when I change the EnableOptimizations property.

UPDATE:

Digging deeper I've found out that BundleTable.Bundles.ResolveBundleUrl and @Scripts.Url seem to have problems to resolve the bundle path.

For sake of simplicity I've added a few images:

image 1

I have turned off the optimization and bundled a few scripts.

image 2

The same bundle is included in the body.

image 3

@Scripts.Url gives me the "optimized" path of the bundle while @Scripts.Render generates the proper one.
Same thing happens with BundleTable.Bundles.ResolveBundleUrl.

I am using Visual Studio 2010 + MVC 4 + Framework .Net 4.0.


Bearing in mind Hao Kung's recommendations to not do this because of web farm scenarios, I think there are a lot of scenarios where you might want to do this. Here is a solution:

BundleTable.Bundles.ResetAll(); //or something more specific if neccesary
var bundle = new Bundle("~/bundles/your-bundle-virtual-path");
//add your includes here or load them in from a config file

//this is where the magic happens
var context = new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, bundle.Path);
bundle.UpdateCache(context, bundle.GenerateBundleResponse(context));

BundleTable.Bundles.Add(bundle);

You can call the above code at any time and your bundles will get updated. This works both when EnableOptimizations is true or false - in other words, this will throw out the correct markup in debug or live scenarios, with:

@Scripts.Render("~/bundles/your-bundle-virtual-path")