我们有一个MVS应用程序,使用Bundle类捆绑javascript代码(不进行缩小)。捆绑工作正常,但当我们运行应用程序时,缓存值设置为Cache-Control:no-cache,同时每次刷新页面时请求总是返回200 OK。这意味着即使没有更改,js也没有被缓存在客户端上。
此外,是否有一种方法可以验证捆绑的js是动态构建的还是从服务器缓存获取的?
谢谢。
我看到了与Codeplex链接中提到的问题相同的行为:
我决定深入了解一下System.Web.Optimization的源代码,看看发生了什么。在Bundle类上,有一个设置头信息的私有方法,它似乎陷入了这段代码中: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
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;
}
}
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();
}
}
由于之前的答案没有帮助到我(不确定后果),我找到了一个解决此问题的方法。
问题在于,正如在这里已经说明的那样,当您在查询字符串上发送?v
且该值与实际哈希值不匹配时,它将返回no-cache
。
完全不发送也不是一个选项(缓存可能永远不会过期)。 发送缓存破坏参数也不是一个选项。如果您这样做,并且您有多个实例,则可能在部署期间对错误的值进行缓存(如果您没有从负载平衡器中删除旧实例)。
为修复此问题,请将UseCdn
设置为false
,并在捆绑配置期间更改以下内容:
Scripts.DefaultTagFormat = string.Format(@"<script src=""{0}{{0}}""></script>", CdnRoot);