7

Bundle クラスを使用して JavaScript コードをバンドルしている MVS アプリケーションがあります (縮小は行わないでください)。

バンドルは正常に機能しますが、アプリケーションを実行すると、キャッシュ値がCache-Control:no-cacheに設定され、同時にページを更新するたびに、リクエストは常に 200 OK になります。これは、何も変更されていないにもかかわらず、js がクライアントにキャッシュされていないことを意味します。

また、バンドルされた js が動的に構築されているか、サーバー キャッシュから取得されているかを確認する方法はありますか?

ありがとう

4

3 に答える 3

8

問題について言及している 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 のようなものに変更しました (この質問に似ています)。バンドル コードは、「1.0.0.0」をバンドル コンテンツの SHA256 ハッシュ コードと比較し、その結果、バンドルにキャッシュなしのフラグを立てています。

コンテンツ ハッシュと一致するようにクエリ文字列を更新することで、これを解決しました。

残念ながら、GetContentHashCode メソッドのアクセス レベルは internal とマークされているため、実装を複製する必要がありました。最終的に、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();
    }
}
于 2016-07-14T18:03:29.157 に答える
2

問題は Microsoft.AspNet.Web.Optimization NuGet パッケージにあるようです。バージョンを 1.3.0 から 1.1.0 にダウングレードした後、すべて正常に動作しているようです。

同じ問題について言及した codeplex のブログ投稿へのリンク

于 2014-04-15T04:26:57.693 に答える