MVC 5 bundling and Azure CDN (query string) MVC 5 bundling and Azure CDN (query string) azure azure

MVC 5 bundling and Azure CDN (query string)


I know I'm a little late to the game, but I did find a workaround. I'm making use of the code by Frison B Alexander here.

The issue is that once you rewrite the querystring for StyleBundles or ScriptBundles, the default caching behavior of one year resets to no-cache. This is solved by regenerating the exact same querystring per bundle that the MVC framework uses when specifying each Bundle's CDNPath.

Here's how it's done using the MVC Web App template. Here's the BundleConfig class:

public class BundleConfig    {        public static void RegisterBundles(BundleCollection bundles)        {                        //we have to go ahead and add our Bundles as if there is no CDN involved.            //this is because the bundle has to already exist in the BundleCollection            //in order to get the hash that the MVC framework will generate for the            //querystring.             Bundle jsBundle = new ScriptBundle("~/scripts/js3").Include(                 "~/Scripts/jquery-{version}.js",                 "~/Scripts/modernizr-*",                 "~/Scripts/bootstrap.js",                 "~/Scripts/respond.js");            bundles.Add(jsBundle);            Bundle cssBundle = new StyleBundle("~/content/css3").Include(                      "~/Content/bootstrap.css",                      "~/Content/site.css");            bundles.Add(cssBundle);#if Debug            bundles.UseCdn = false; #else            bundles.UseCdn = true;            //grab our base CDN hostname from web.config...            string cdnHost = ConfigurationManager.AppSettings["CDNHostName"];            //get the hashes that the MVC framework will use per bundle for             //the querystring.             string jsHash = GetBundleHash(bundles, "~/scripts/js3");            string cssHash = GetBundleHash(bundles, "~/content/css3");            //set up our querystring per bundle for the CDN path.             jsBundle.CdnPath = cdnHost + "/scripts/js3?v=" + jsHash;            cssBundle.CdnPath = cdnHost + "/content/css3?v=" + cssHash;#endif        }        //Frison B Alexander's code:        private static string GetBundleHash(BundleCollection bundles, string bundlePath)        {            //Need the context to generate response            var bundleContext = new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, bundlePath);            //Bundle class has the method we need to get a BundleResponse            Bundle bundle = BundleTable.Bundles.GetBundleFor(bundlePath);            var bundleResponse = bundle.GenerateBundleResponse(bundleContext);            //BundleResponse has the method we need to call, but its marked as            //internal and therefor is not available for public consumption.            //To bypass this, reflect on it and manually invoke the method            var bundleReflection = bundleResponse.GetType();            var method = bundleReflection.GetMethod("GetContentHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);            //contentHash is whats appended to your url (url?###-###...)            var contentHash = method.Invoke(bundleResponse, null);            return contentHash.ToString();         }    }