c# - MVC4 脚本包缓存问题

标签 c# asp.net asp.net-mvc-4 bundles

我们有一个 MVS 应用程序,我们在其中使用 Bundle 类捆绑 javascript 代码(不要进行缩小)。

捆绑工作正常,但是当我们运行应用程序时,缓存值设置为 Cache-Control:no-cache 同时每次我们刷新页面时请求总是有一个200 好。这意味着即使没有任何更改,js 也不会缓存在客户端上。

还有一种方法可以验证捆绑的 js 是动态构建的还是从服务器缓存中获取的?

谢谢

最佳答案

我看到了与提到该问题的 codeplex 链接中描述的相同行为:

i.e. if I visit these URLs in the following order then the behaviour is -

bundle.css?v=1234 : no-cache
bundle.css : public
bundle.css?v=1234 : public

我决定深入研究 System.Web.Optimization 源代码,看看发生了什么。在Bundle类上,有一个私有(private)方法设置headers,貌似落入了这段代码:

if (noCache) {
    cachePolicy.SetCacheability(HttpCacheability.NoCache);
}

noCache 变量是通过参数设置的。这种情况下的调用方法是设置它:

// Set to no-cache if the version requested does not match
bool noCache = false;
var request = context.HttpContext.Request;
if (request != null) {
    string queryVersion = request.QueryString.Get(VersionQueryString);
        if (queryVersion != null && bundleResponse.GetContentHashCode() != queryVersion) {
                noCache = true;
    }
}

长话短说,我们已经切换到使用 Azure CDN 进行捆绑,并根据程序集版本将版本查询字符串参数更改为类似 ?v=1.0.0.0 的内容(类似于 this question )。 bundle 代码将“1.0.0.0”与 bundle 内容的 SHA256 哈希码进行比较,并将 bundle 标记为无缓存。

我通过更新我们的查询字符串以匹配内容哈希来解决这个问题。

不幸的是,GetContentHashCode 方法的访问级别标记为内部,因此有必要复制 implementation .我最终创建了一个继承自 Bundle 的类,以便它可以将版本号作为转换应用于 CdnPath:

public class ProxiedCdnBundle : Bundle
{
    private readonly string _cdnHost;

    public ProxiedCdnBundle(string virtualPath, string cdnHost = "")
        : base(virtualPath)
    {
        _cdnHost = cdnHost;
    }

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

        if (context.BundleCollection.UseCdn && !String.IsNullOrWhiteSpace(_cdnHost))
        {
            string path = System.Web.VirtualPathUtility.ToAbsolute(context.BundleVirtualPath);
            base.CdnPath = string.Format("{0}{1}?v={2}", _cdnHost, path, GetBundleHash(response));
        }

        return response;
    }


    private static string GetBundleHash(BundleResponse response)
    {
        using (var hashAlgorithm = CreateHashAlgorithm())
        {
            return HttpServerUtility.UrlTokenEncode(hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(response.Content)));
        }
    }

    private static SHA256 CreateHashAlgorithm()
    {
        if (CryptoConfig.AllowOnlyFipsAlgorithms)
        {
            return new SHA256CryptoServiceProvider();
        }

        return new SHA256Managed();
    }
}

关于c# - MVC4 脚本包缓存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23052818/

相关文章:

c# - 检查c#方法的速度和内存大小

asp.net - 无需身份验证的 URL 重写

.net - IIS 7.5 自动启动无法与使用 Web Activator 的 Ninject 一起使用

c# - Put call 在 PostMan 中有效,但在 RestSharp 中无效 : Getting a bad request

c# - WPF 将内容展开到窗口外

c# - 如何检查泛型类型参数是否可为空?

c# - 如何使用 Javascript 或 JQuery 获取页面内容

c# - 使我的 ASP.NET 网站与 Firefox 兼容?

c# - 错误 : The model item passed into the dictionary is null, 但此字典需要类型为 'System.DateTime' 的非空模型项

c# - 如何在 Asp.net MVC4 中避免 PostBack