web-dev-qa-db-ja.com

キャッシュ制御:IIS7 + ASP.NET MVCでクライアントブラウザに送信されない、ストアなし、再検証が必要

特定のページがキャッシュされず、ユーザーが[戻る]ボタンをクリックしたときに表示されないようにしようとしています。 この非常に高い評価の回答(現在1068の賛成票)は使用するように言っています

_Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
_

ただし、IIS7/ASP.NET MVCでは、これらのヘッダーを送信すると、クライアントには代わりにこれらの応答ヘッダーが表示されます。

_Cache-control: private, s-maxage=0 // that's not what I set them to
Pragma: no-cache
Expires: 0
_

Cache-controlヘッダーはどうなりましたか? IIS7またはASP.NETに固有のものが上書きしますか?ソリューションを確認しましたが、このヘッダーを上書きするコードはありません。

最初にResponse.Headers.Remove("Cache-Control");を追加しても、違いはありません。

_Response.Headers.Remove("Cache-Control");
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
_

_[OutputCache]_属性を追加すると:

_[OutputCache(Location = OutputCacheLocation.None)]
public ActionResult DoSomething()
{
   Response.Headers.Remove("Cache-Control");
   Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
   Response.AppendHeader("Pragma", "no-cache");
   Response.AppendHeader("Expires", "0");

   var model = DoSomething();
   return View(model);
}
_

次に、クライアントの応答ヘッダーが次のように変更されます。

_Cache-control: no-cache
Pragma: no-cache
Expires: 0
_

これは近いですが、まだ送信したいヘッダーではありません。これらのヘッダーはどこでオーバーライドされ、どのように停止できますか?

編集:私はチェックし、間違ったヘッダーがChrome、FF、IEとSafariに送信されているので、ブラウザ関連の問題ではなくサーバーの問題のようです。

27
JK.

試行錯誤を通して、ASP.NET MVCでIIS7のヘッダーを正しく設定する方法の1つが次のとおりであることがわかりました。

_Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
_

最初の行は_Cache-control_を_no-cache_に設定し、2行目は他の属性_no-store, must-revalidate_を追加します。

これが唯一の方法ではないかもしれませんが、より簡単なResponse.AppendHeader("Cache-control", "no-cache, no-store, must-revalidate");が失敗した場合の代替方法を提供します。

これによって解決される可能性のある他の関連するIIS7キャッシュ制御の質問は次のとおりです。

42
JK.

これらのヘッダーがMVCアプリケーションでグローバルに必要な場合。このクラスを追加します。

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class CustomHeaders : System.Web.Mvc.ActionFilterAttribute
{
    [OutputCache(Location = System.Web.UI.OutputCacheLocation.None)]
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.RequestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.RequestContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
        context.RequestContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
        context.RequestContext.HttpContext.Response.AppendHeader("Expires", "0");

        base.OnActionExecuted(context);
    }
}

グローバルに使用するには、FilterConfigに追加します。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new CustomHeaders());
    }
}

または、特定のコントローラーでのみこれらのヘッダーを使用します。

[Authorize]
[CustomHeaders]
public class HomeController : Controller
{
    [AllowAnonymous]
    public ActionResult Index()

補足:他のヘッダーにはIISおよびweb.configを使用できます。たとえば、バンドル(jquery、bootstrap)などの静的コンテンツの場合。これらのセクションcustomheaders、staticcontentを探します。

0
ivw

[〜#〜] jk [〜#〜] の答えに何かを追加したい:
キャッシュ制御を既に制限されている値よりも制限された値に設定している場合は、問題ありません。 (つまり、プライベートの場合、no-cacheを設定します)

ただし、既存の値よりも制限の少ない値(つまり、キャッシュなしの場合にプライベートに設定)に設定する場合、以下のコードは機能しません。

Response.Cache.SetCacheability(HttpCacheability.Private);

SetCacheablitiyメソッドには以下のコードがあり、より制限的な場合にのみキャッシュフラグを設定するためです。

if (s_cacheabilityValues[(int)cacheability] < s_cacheabilityValues[(int)_cacheability]) {
    Dirtied();
   _cacheability = cacheability;
}

.net mvcでこれを克服するには、HttpResponseMessageのインスタンスを取得し、CacheControlHeaderValueをそのHeaders.CacheControl値に割り当てる必要があります。

actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue
                                   {
                                       MaxAge = TimeSpan.FromSeconds(3600),
                                       Private = true
                                   };

HttpResponseMessageのインスタンスは、アクションフィルターで使用できます。次のようなキャッシュヘッダー値を設定するアクションフィルターを作成できます。

public class ClientSideCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var response = actionExecutedContext.ActionContext.Response;
        response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue
        {
            MaxAge = TimeSpan.FromSeconds(9999),
            Private = true,
        };
    }
}
0
Veysel Özdemir