MVC4 StyleBundle:你能在Debug模式下添加缓存破坏查询字符串吗?

gro*_*wse 47 caching bundle asp.net-mvc-4

我有一个MVC应用程序,我正在使用StyleBundle该类来渲染CSS文件,如下所示:

bundles.Add(new StyleBundle("~/bundles/css").Include("~/Content/*.css"));
Run Code Online (Sandbox Code Playgroud)

Debug我遇到的问题是,在模式下,CSS网址是单独呈现出来的,我有一个网络代理,可以积极地缓存这些网址.在Release模式中,我知道查询字符串被添加到最终URL以使每个版本的任何缓存无效.

是否可以配置StyleBundleDebug模式中添加随机查询字符串以产生以下输出以解决缓存问题?

<link href="/stylesheet.css?random=some_random_string" rel="stylesheet"/>
Run Code Online (Sandbox Code Playgroud)

bin*_*les 46

您可以创建自定义IBundleTransform类来执行此操作.这是一个使用文件内容的散列附加av = [filehash]参数的示例.

public class FileHashVersionBundleTransform: IBundleTransform
{
    public void Process(BundleContext context, BundleResponse response)
    {
        foreach(var file in response.Files)
        {
            using(FileStream fs = File.OpenRead(HostingEnvironment.MapPath(file.IncludedVirtualPath)))
            {
                //get hash of file contents
                byte[] fileHash = new SHA256Managed().ComputeHash(fs);

                //encode file hash as a query string param
                string version = HttpServerUtility.UrlTokenEncode(fileHash);
                file.IncludedVirtualPath = string.Concat(file.IncludedVirtualPath, "?v=", version);
            }                
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过将类添加到捆绑包的Transforms集合来注册该类.

new StyleBundle("...").Transforms.Add(new FileHashVersionBundleTransform());
Run Code Online (Sandbox Code Playgroud)

现在版本号只会在文件内容改变时改变.

  • 为什么不直接使用LastWrite文件.然后你不必为SHA256做所有磁盘读取和CPU.如果你坚持散列,MD5就足够了 - 你不是在安全之后,你是在一个具有低CPU周期的独特散列(足够好)之后. (6认同)
  • 不行不通,你的例子对我不起作用 - response.Files是一个可容忍的FileInfo对象.(Web.Optimization Version = 1.0.0.0).看起来您需要使用版本1.1+ (2认同)

H D*_*Dog 41

你只需要一个独特的字符串.它不一定是哈希.我们使用文件的LastModified日期并从那里获取Ticks.正如@Todd所说,打开和阅读文件很昂贵.刻度足以输出在文件更改时更改的唯一编号.

internal static class BundleExtensions
{
    public static Bundle WithLastModifiedToken(this Bundle sb)
    {
        sb.Transforms.Add(new LastModifiedBundleTransform());
        return sb;
    }
    public class LastModifiedBundleTransform : IBundleTransform
    {
        public void Process(BundleContext context, BundleResponse response)
        {
            foreach (var file in response.Files)
            {
                var lastWrite = File.GetLastWriteTime(HostingEnvironment.MapPath(file.IncludedVirtualPath)).Ticks.ToString();
                file.IncludedVirtualPath = string.Concat(file.IncludedVirtualPath, "?v=", lastWrite);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以及如何使用它:

bundles.Add(new StyleBundle("~/bundles/css")
    .Include("~/Content/*.css")
    .WithLastModifiedToken());
Run Code Online (Sandbox Code Playgroud)

这就是MVC所写的:

<link href="bundles/css/site.css?v=635983900813469054" rel="stylesheet"/>
Run Code Online (Sandbox Code Playgroud)

也适用于Script bundle.


Raf*_*afe 13

这个库可以在调试模式下将缓存破坏哈希添加到您的包文件中,以及其他一些缓存破坏的东西:https://github.com/kemmis/System.Web.Optimization.HashCache

您可以将HashCache应用于BundlesCollection中的所有捆绑包

所有捆绑包添加到集合后,在BundlesCollection实例上执行ApplyHashCache()扩展方法 .

BundleTable.Bundles.ApplyHashCache();
Run Code Online (Sandbox Code Playgroud)

或者您可以将HashCache应用于单个Bundle

创建HashCacheTransform的实例并将其添加到要应用HashCache的bundle实例.

var myBundle = new ScriptBundle("~/bundle_virtual_path").Include("~/scripts/jsfile.js");
myBundle.Transforms.Add(new HashCacheTransform());
Run Code Online (Sandbox Code Playgroud)


Joh*_*Gov 8

我有同样的问题,但升级后在客户端浏览器中使用缓存版本.我的解决方案是将调用包装@Styles.Render("~/Content/css")在我自己的渲染器中,该渲染器将我们的版本号附加在查询字符串中,如下所示:

    public static IHtmlString RenderCacheSafe(string path)
    {
        var html = Styles.Render(path);
        var version = VersionHelper.GetVersion();
        var stringContent = html.ToString();

        // The version should be inserted just before the closing quotation mark of the href attribute.
        var versionedHtml = stringContent.Replace("\" rel=", string.Format("?v={0}\" rel=", version));
        return new HtmlString(versionedHtml);
    }
Run Code Online (Sandbox Code Playgroud)

然后在视图中我喜欢这样:

@RenderHelpers.RenderCacheSafe("~/Content/css")
Run Code Online (Sandbox Code Playgroud)