I was seeing the same behavior as described in codeplex link that mentions the issue:
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
I decided to dig into the System.Web.Optimization source code a bit to see what was going on. On the Bundle class, there is a private method setting headers, and it appears to be falling into this code:
if (noCache) {
cachePolicy.SetCacheability(HttpCacheability.NoCache);
}
The noCache variable is set via a parameter. The calling method in this case is setting it:
// 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;
}
}
Long story short, we had switched to using Azure CDN for our bundles and changed the version query string parameter to something like ?v=1.0.0.0 based on the assembly version (similar to on this question). The bundle code is comparing "1.0.0.0" with the SHA256 hash code of the bundle content and flagging the bundle for no-cache as a result.
I resolved this by updating our query string to match the content hash.
Unfortunately the access level for the GetContentHashCode method is marked internal, so it was necessary to replicate the implementation. I ended up creating a class that inherited from Bundle so that it could apply the version number to the CdnPath as a transform:
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();
}
}