使用CDN和HashContent(Cache Buster或指纹)的ASP.NET优化框架(JS和CSS缩小和捆绑)

Rom*_*Mik 5 asp.net asp.net-mvc optimization bundling-and-minification

!警告!!!

接受的答案是好的,但如果你有一个高流量的网站,有可能多次附加v =.该代码包含一个检查器.

我一直在寻找使用ASP.NET优化框架和UseCDN = true并且HashContent Number附加到Bundles的URI的任何示例或引用.不幸没有运气.以下是我的代码的简化示例.

我的捆绑代码非常简单

        bundles.UseCdn = true;

        BundleTable.EnableOptimizations = true;


        var stylesCdnPath = "http://myCDN.com/style.css";
        bundles.Add(new StyleBundle("~/bundles/styles/style.css", stylesCdnPath).Include(
            "~/css/style.css"));
Run Code Online (Sandbox Code Playgroud)

我从Master页面调用Render

 <%: System.Web.Optimization.Styles.Render("~/bundles/styles/style.css")%>
Run Code Online (Sandbox Code Playgroud)

生成的代码是

 <link href="http://myCDN.com/style.css" rel="stylesheet"/>
Run Code Online (Sandbox Code Playgroud)

如果我禁用UseCDN

 /bundles/styles/style.css?v=geCEcmf_QJDXOCkNczldjY2sxsEkzeVfPt_cGlSh4dg1
Run Code Online (Sandbox Code Playgroud)

当useCDN设置为true时,如何使bunlding添加v =哈希内容?

编辑:

我试过用

 <%: System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/styles/style.css",true)%> 
Run Code Online (Sandbox Code Playgroud)

如果CdnUse = true,它仍然不会生成v = hash

MK.*_*MK. 8

你不能,设置UseCdntrue意味着ASP.NET将按照你的CDN路径提供捆绑服务,不会执行捆绑和缩小.

查询字符串v具有值标记,该标记是用于高速缓存的唯一标识符.只要捆绑包没有更改,ASP.NET应用程序就会使用此令牌请求捆绑包.如果包中的任何文件发生更改,ASP.NET优化框架将生成一个新令牌,保证对该包的浏览器请求将获得最新的包.

看看BundleCollection.ResolveBundleUrl实施:

// System.Web.Optimization.BundleCollection
/// <summary>Returns the bundle URL for the specified virtual path, including a content hash if requested.</summary>
/// <returns>The bundle URL or null if the bundle cannot be found.</returns>
/// <param name="bundleVirtualPath">The virtual path of the bundle.</param>
/// <param name="includeContentHash">true to include a hash code for the content; otherwise, false. The default is true.</param>
public string ResolveBundleUrl(string bundleVirtualPath, bool includeContentHash)
{
    Exception ex = ExceptionUtil.ValidateVirtualPath(bundleVirtualPath, "bundleVirtualPath");
    if (ex != null)
    {
        throw ex;
    }
    Bundle bundleFor = this.GetBundleFor(bundleVirtualPath);
    if (bundleFor == null)
    {
        return null;
    }
    if (this.UseCdn && !string.IsNullOrEmpty(bundleFor.CdnPath))
    {
        return bundleFor.CdnPath;
    }
    return bundleFor.GetBundleUrl(new BundleContext(this.Context, this, bundleVirtualPath), includeContentHash);
}
Run Code Online (Sandbox Code Playgroud)

参考:http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

更新

您可以通过实现自己的捆绑包并在ApplyTransforms调用时生成哈希值,将V哈希手动添加到您的CDN :

public class myStyleBundle: StyleBundle
{
  public myStyleBundle(string virtualPath)
    :base(virtualPath)
  {          
  }

  public myStyleBundle(string virtualPath, string cdnPath)
    : base(virtualPath,cdnPath)
  {
    MyCdnPath = cdnPath;
  }

  public string MyCdnPath
  {
    get;
    set;
  }

  public override BundleResponse ApplyTransforms(BundleContext context, string bundleContent, System.Collections.Generic.IEnumerable<BundleFile> bundleFiles)
  {
    var response = base.ApplyTransforms(context, bundleContent, bundleFiles);

    base.CdnPath = string.Format("{0}?v={1}", this.MyCdnPath, this.HashContent(response));

    return response;
  }

  private string HashContent(BundleResponse response)
  {
    string result;
    using (SHA256 sHA = new SHA256Managed())
    {
      byte[] input2 = sHA.ComputeHash(Encoding.Unicode.GetBytes(response.Content));
      result = HttpServerUtility.UrlTokenEncode(input2);
    }
    return result;
  }

}
Run Code Online (Sandbox Code Playgroud)

然后,只需:

bundles.Add(new myStyleBundle("~/bundles/styles/style.css", stylesCdnPath).Include(
           "~/css/style.css"));
Run Code Online (Sandbox Code Playgroud)

请注意,System.Web.Optimization.BundleResponse根据环境设置创建哈希算法:

// System.Web.Optimization.BundleResponse
private static SHA256 CreateHashAlgorithm()
{
  if (BundleResponse.AllowOnlyFipsAlgorithms)
  {
     return new SHA256CryptoServiceProvider();
  }
  return new SHA256Managed();
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.@MK.您提供的解决方案就是我一直在寻找的解决方案.我需要V哈希的原因是破坏用户的缓存并强制他们的浏览器更新脚本/样式.这也迫使我的CDN刷新其缓存,并从我的服务器请求新版本.我很惊讶这个选项没有在框架中实现.似乎很多网站都使用带有CDN的缓存. (4认同)