ASP.NET MVC3 で ブラウザ キャッシュ を 無効化 する アクションフィルター

0 件のコメント

特定の処理だけ キャッシュ を 無効化 したいけれど、いちいち、そんな処理を書いているのが面倒… という思いから、お手軽に キャッシュ の 無効化 を実現する方法を作ってみました。

無効化する作業としては、以下のソースコードにある NoCacheAttribute をキャッシュさせたくない操作(メソッド)の属性に設定するだけです。

ソースコード

キャッシュ を 無効化する 属性 NoCacheAttribute のサンプルコードを以下に記載します。

NoCacheAttribute.cs

namespace SampleMvcApplication.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;

    /// <summary>
    /// キャッシュを無効化するフィルター属性を表します。
    /// </summary>
    public class NoCacheAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// アクション メソッドの実行後に ASP.NET MVC フレームワークによって呼び出されます。
        /// </summary>
        /// <param name="filterContext">フィルダー コンテキスト</param>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // 継承元の処理を実行
            base.OnActionExecuted(filterContext);

            // レスポンスヘッダーにキャッシュ無効化を追加
            var response = filterContext.HttpContext.Response;
            response.Cache.SetCacheability(HttpCacheability.NoCache);
        }
    }
}

説明

ActionFilterAttribute クラスを継承した、NoCacheAttribute クラスを作成します。

すべてのサーバー処理が終わって、クライアントへ配信する直前(OnActionExecuted)に、キャッシュしないヘッダーを付加する処理を記載します。 この処理により、サーバーからクライアントへのレスポンスヘッダーでは次のようなヘッダーが追加されます。

  • Cache-Control: no-cache
  • Expires: -1
  • Pragma: no-cache

…冒頭で "いちいち、そんな処理を書いているのが面倒…" と書いていますが、実際書く処理は 1行 です。 どちらかと言うと、"コーディングがラクになる" より "可読性が良くなる" が正しいかもしれません。

使用例

上記 サンプルコード で書いた コード を利用してみます。 この コード では Test メソッドで呼ばれる内容が キャッシュ されなくなります。

サンプルコード

[NoCache]
public ActionResult Test()
{
    // レスポンス用のサンプルデータを作成
    var o = new
    {
        Message = "foo-bar",
        DateTime = DateTime.Now.ToString("r")
    };

    // 作成したデータを返信
    return this.Json(o, JsonRequestBehavior.AllowGet);
}

この アクションフィルター では、 .cshtml 等に記述された img タグ、link タグ、script タグで後から呼び出されるファイルに対して、 キャッシュ を 無効化 させることはできません。 これらの ファイル も含めて 無効化 したい場合、 web.config の修正をご検討ください(→参考(GUI設定)参考(XML直編集))。

今回、参考にしたサイトは以下の通りです。

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!