Guillaume
Guillaume

Reputation: 13138

Use CDN for ASP MVC Bundle with version tag

I'd like to use CDN with my Bundles but ASP MVC doesn't handle version natively for CDN urls.

For instance :

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.UseCdn = true;   //enable CDN support

    //add link to jquery on the CDN
    var jqueryCdnPath = 
        "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js";

    bundles.Add(new ScriptBundle("~/bundles/jquery",
                jqueryCdnPath).Include(
                "~/Scripts/jquery-{version}.js"));
}

I can't use {version} tag Inside jqueryCdnPath, the Framewok has no way to know that I want the local version in the remote url. Is there a way to workaround this limitation ? How can I retrieve the local version to build the CDN url ?

Upvotes: 2

Views: 553

Answers (1)

Guillaume
Guillaume

Reputation: 13138

I have an option but it only works when the {version} tag is used in virtualPath. Some scripts (bootstrap, globalize,...) doesn't need a version tag and I have no way to know the version number to reference on the CDN.

private static string GetLastIncludedVirtualPath(this Bundle bundle)
{
  var files = bundle.EnumerateFiles(new BundleContext(new HttpContextWrapper(HttpContext.Current), new BundleCollection(), ""));
  var lastFile = files.LastOrDefault();
  if (lastFile == null)
    throw new InvalidOperationException("You must include a file so version can be extracted");
  return lastFile.IncludedVirtualPath;
}

public static Bundle IncludeWithVersionnedCdn(this Bundle bundle, string virtualPath, string cdnPath, params IItemTransform[] transforms)
{
  if (bundle == null)
    throw new ArgumentNullException("bundle");
  if (cdnPath == null)
    throw new ArgumentNullException("cdnPath");
  bundle.Include(virtualPath, transforms);
  //GetVersion
  int lengthBeforeVersion = virtualPath.IndexOf("{version}", StringComparison.OrdinalIgnoreCase);
  if (lengthBeforeVersion == -1)
    throw new ArgumentException("Path must contains {version} when version argument is not specified", "virtualPath");
  var includedPath = bundle.GetLastIncludedVirtualPath();
  int lengthAfterVersion = virtualPath.Length - lengthBeforeVersion - "{version}".Length;
  string version = includedPath.Remove(includedPath.Length - lengthAfterVersion).Substring(lengthBeforeVersion);
  //Set CDN
  bundle.CdnPath = cdnPath.Replace("{version}", version);
  return bundle;
}

Usage :

bundles.Add(new ScriptBundle("~/bundles/jquery")
                .IncludeWithVersionnedCdn(
                    "~/Scripts/jquery-{version}.js",
                    "//ajax.aspnetcdn.com/ajax/jQuery/jquery-{version}.min.js"));

Upvotes: 2

Related Questions