我们有一个MVS应用程序,我们使用Bundle类捆绑javascript代码(不要做缩小)。
捆绑工作正常,但是当我们运行应用程序时,缓存值设置为缓存控制:无缓存,同时每次刷新页面时请求总是有一个200好的。这意味着即使没有任何更改,js也不会缓存在客户端上。
还有办法验证捆绑的js是动态构建还是从服务器缓存中获取?
由于
答案 0 :(得分:6)
我看到了与codeplex链接中描述的相同的行为,提到了这个问题:
即。如果我按以下顺序访问这些URL,则行为是 -
bundle.css?v=1234 : no-cache bundle.css : public bundle.css?v=1234 : public
我决定深入研究一下System.Web.Optimization源代码,看看发生了什么。在Bundle类中,有一个私有方法设置标题,它似乎属于这段代码:
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)。捆绑代码正在比较" 1.0.0.0"使用捆绑内容的SHA256哈希码并将结果标记为无缓存的束。
我通过更新查询字符串来匹配内容哈希来解决这个问题。
不幸的是,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();
}
}
答案 1 :(得分:2)
问题似乎与Microsoft.AspNet.Web.Optimization NuGet包有关。将版本从1.3.0降级到1.1.0后,一切似乎都运行正常。
Link to blog post on codeplex which mentioned the same issue
答案 2 :(得分:1)
由于上述答案对我没有帮助(不确定后果),我找到了解决此问题的方法。
如上所述,问题在于,当您在查询字符串上发送no-cache
并且该值与实际哈希值不匹配时,它将返回UseCdn
。
根本不发送任何内容不是一个选项(缓存可能永远不会过期)。 发送缓存清除参数也不是一种选择。如果您这样做并且您有多个实例,则可能在部署期间缓存错误的值(如果您没有从负载均衡器中删除旧实例)。
要解决此问题,只需将false
设置为Scripts.DefaultTagFormat = string.Format(@"<script src=""{0}{{0}}""></script>", CdnRoot);
,然后在捆绑配置期间更改以下内容:
{{1}}
希望,我帮助了。