ASP.NET Core の応答キャッシュ

作成者: Rick Anderson および Kirk Larkin

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

応答キャッシュを使用すると、クライアントまたはプロキシから Web サーバーに対して行う要求の数が減ります。 応答キャッシュを使用することで、Web サーバーで応答を生成するために実行される作業量も減ります。 応答キャッシュはヘッダーで設定されます。

ResponseCache 属性は、応答キャッシュ ヘッダーを設定します。 クライアントと中間プロキシでは、 RFC 9111: HTTP キャッシュに基づく応答をキャッシュするためのヘッダーを使用する必要があります。

HTTP 1.1 キャッシュ仕様に従うサーバー側キャッシュのためには、応答キャッシュ ミドルウェアを使用します。 ミドルウェアで ResponseCacheAttribute プロパティを使用すると、サーバー側キャッシュの動作に影響を与えることができます。

応答キャッシュ ミドルウェア:

  • HTTP キャッシュ ヘッダーに基づくサーバー応答のキャッシュを有効にします。 標準の HTTP キャッシュ セマンティクスを実装します。 プロキシのような HTTP キャッシュ ヘッダーに基づくキャッシュ。
  • 通常、ブラウザーによってキャッシュを防ぐ要求ヘッダーが設定されるため、Razor Pages などの UI アプリには有益ではありません。 出力キャッシュは、ASP.NET Core 7.0 以降で使用でき、UI アプリにメリットがあります。 出力キャッシュでは、HTTP ヘッダーとは別にキャッシュする必要がある内容が構成によって決定されます。
  • キャッシュの条件が満たされているクライアントからのパブリック GET または HEAD API 要求 に役立 つ場合があります。

応答キャッシュをテストするには、 FiddlerPostman、または要求ヘッダーを明示的に設定できる別のツールを使用します。 キャッシュをテストするには、ヘッダーを明示的に設定することをお勧めします。 詳細については、トラブルシューティングのヒントに関するページをご覧ください。

HTTP ベースの応答キャッシュ

RFC 9111: HTTP キャッシュ では、インターネット キャッシュの動作について説明します。 キャッシュに使用されるプライマリ HTTP ヘッダーは Cache-Control であり、キャッシュ ディレクティブを指定するために使用されます。 ディレクティブは、クライアントからサーバーに要求が送られるとき、さらにサーバーからクライアントに応答が返されるときのキャッシュの動作を制御します。 要求と応答はプロキシ サーバー間を移動し、プロキシ サーバーも HTTP 1.1 キャッシュ仕様に準拠している必要があります。

一般的な Cache-Control ディレクティブを次の表に示します。

ディレクティブ アクション
public キャッシュに応答を格納できます。
private 共有キャッシュによる応答の格納は禁止されます。 プライベート キャッシュに応答を格納し、再利用することができます。
max-age クライアントは、経過時間が指定の秒数を超えた応答を受け入れません。 例: max-age=60 (60 秒)、max-age=2592000 (1 か月)
no-cache 要求時: キャッシュに格納された応答を、要求を満たすために使用することはできません。 オリジン サーバーはクライアントに対する応答を再生成し、キャッシュ内に格納されている応答がミドルウェアによって更新されます。

応答時: オリジン サーバー上での検証なしに後続の要求に応答を使用することはできません。
no-store 要求時: キャッシュに要求を格納することは禁止されます。

応答時: キャッシュに応答を一部でも格納することは禁止されます。

キャッシュで役割を果たすその他のキャッシュ ヘッダーを次の表に示します。

ヘッダー 機能
Age オリジン サーバーで応答が生成されたか正常に検証されてから以降の推定時間 (秒単位)。
Expires それより後は応答が古いと見なされる日時。
Pragma no-cache 動作を設定する場合の HTTP/1.0 キャッシュとの下位互換性を確保するために存在します。 Cache-Control ヘッダーが存在する場合、Pragma ヘッダーは無視されます。
Vary キャッシュされた応答の最初要求と新しい要求の両方で、すべての Vary ヘッダー フィールドが一致しない限り、キャッシュされた応答を送信してはならないことを指定します。

HTTP ベースのキャッシュで要求の Cache-Control ディレクティブに従う

RFC 9111: HTTP キャッシュ (セクション 5.2.Cache-Control) には、クライアントから送信された有効なヘッダーを優先するキャッシュが必要です Cache-Control 。 クライアントは、no-cache ヘッダー値を使用して要求を行うことで、すべての要求に対してサーバーに新しい応答を強制的に生成させることができます。

HTTP キャッシュの目標を考えると、クライアントの Cache-Control 要求ヘッダーに常に従うことは理にかなっています。 公式仕様では、キャッシュはクライアント、プロキシ、およびサーバーのネットワーク全体で要求を満たすための待機時間とネットワーク オーバーヘッドを削減することを目的としています。 これは必ずしもオリジン サーバーの負荷を制御する方法ではありません。

応答キャッシュ ミドルウェアを使用する場合、このキャッシュ動作を開発者が制御することはできません。ミドルウェアは公式のキャッシュ仕様に準拠しているためです。 サーバーの負荷をより適切に制御するための "出力キャッシュ" のサポートは、ASP.NET Core の今後のリリースに向けての設計提案となっています。 詳細については、出力キャッシュのサポートの追加 (dotnet/aspnetcore #27387)に関するページを参照してください。

ResponseCache 属性

ResponseCacheAttribute は、応答キャッシュで適切なヘッダーを設定するために必要なパラメーターを指定します。

警告

認証されたクライアントに関する情報を含むコンテンツのキャッシュを無効にします。 キャッシュは、ユーザーの ID またはユーザーがサインイン済みかどうかに基づいて変更されることのないコンテンツに対してのみ有効にする必要があります。

VaryByQueryKeys は、指定されたクエリ キーの一覧の値によって、格納された応答を変化させます。 * の単一の値が指定されている場合、応答はミドルウェアによって、すべての要求クエリ文字列パラメーターに応じて変化させられます。

VaryByQueryKeys プロパティを設定するには、応答キャッシュ ミドルウェアを有効にする必要があります。 そうしないと、ランタイム例外がスローされます。 VaryByQueryKeys プロパティに対応する HTTP ヘッダーは存在しません。 このプロパティは、応答キャッシュ ミドルウェアによって処理される HTTP 機能です。 キャッシュされた応答をミドルウェアで処理するには、クエリ文字列とクエリ文字列値が前の要求と一致する必要があります。 たとえば、次の表に示す一連の要求と結果について考えてみましょう。

Request から返されます
http://example.com?key1=value1 サーバー
http://example.com?key1=value1 ミドルウェア
http://example.com?key1=NewValue サーバー

最初の要求はサーバーによって返され、ミドルウェアにキャッシュされます。 2 番目の要求は、クエリ文字列が前の要求と一致するため、ミドルウェアによって返されます。 3 番目の要求は、クエリ文字列の値が前の要求と一致しないため、ミドルウェア キャッシュ内に存在しません。

ResponseCacheAttribute は、(IFilterFactory を使用して) Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter を構成および作成するために使用されます。 ResponseCacheFilter は、応答の適切な HTTP ヘッダーと機能を更新する処理を実行します。 フィルターにより次のことが行われます。

  • VaryCache-ControlPragmaの既存ヘッダーがあれば削除します。
  • ResponseCacheAttribute で設定されたプロパティに基づいて、適切なヘッダーを書き出します。
  • VaryByQueryKeys が設定されている場合は、応答キャッシュの HTTP 機能を更新します。

Vary

このヘッダーは、VaryByHeader プロパティが設定されている場合にのみ書き込まれます。 そのプロパティは Vary プロパティの値に設定されます。 次のサンプルでは、VaryByHeader プロパティを使用しています。

[ApiController]
public class TimeController : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    [ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

Fiddler または別のツールを使用して応答ヘッダーを表示します。 応答ヘッダーには、次のものが含まれます。

Cache-Control: public,max-age=30
Vary: User-Agent

上記のコードでは、応答キャッシュ ミドルウェア サービス AddResponseCaching をサービス コレクションに追加する必要があり、拡張メソッドでミドルウェアを使用するようにアプリを UseResponseCaching 構成します。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseHttpsRedirection();

// UseCors must be called before UseResponseCaching
//app.UseCors();

app.UseResponseCaching();

app.UseAuthorization();

app.MapControllers();

app.Run();

NoStore および Location.None

NoStore は、他のほとんどのプロパティをオーバーライドします。 このプロパティを true に設定すると、Cache-Control ヘッダーが no-store に設定されます。 LocationNone に設定すると、次のようになります。

  • Cache-Controlno-store,no-cache に設定されます。
  • Pragmano-cache に設定されます。

NoStorefalseLocationNone の場合、Cache-ControlPragmano-cache に設定されます。

NoStore は通常、エラー ページに対して true に設定されます。 次の例では、応答を格納しないようにクライアントに指示する応答ヘッダーが生成されます。

[Route("api/[controller]/ticks")]
[HttpGet]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public ContentResult GetTimeTicks() => Content(
                  DateTime.Now.Ticks.ToString());

上記のコードには、応答に次のヘッダーが含まれています。

Cache-Control: no-store,no-cache
Pragma: no-cache

アプリのすべての MVC コントローラーまたは Pages ページ応答に を適用ResponseCacheAttributeするには、MVC フィルターまたは RazorRazor Pages フィルターを使用して追加します。

MVC アプリの場合:

builder.Services.AddControllersWithViews().AddMvcOptions(options => 
    options.Filters.Add(
        new ResponseCacheAttribute
        {
            NoStore = true, 
            Location = ResponseCacheLocation.None
        }));

Pages アプリに Razor 適用される方法については、「 MVC グローバル フィルター リストへの追加 ResponseCacheAttribute は Pages に適用 Razor されません (dotnet/aspnetcore #18890)」を参照してください。 問題のコメントに記載されている例は、6.0 で最小 API がリリースされる前に、ASP.NET Coreを対象とするアプリ用に作成されました。 6.0 以降のアプリの場合は、例 builder.Services.AddSingleton... のサービス登録を に変更します Program.cs

Location と Duration

キャッシュを有効にするには、Duration を正の値に設定し、LocationAny (既定値) または Client にする必要があります。 フレームワークによって、Cache-Control ヘッダーが location 値に設定され、その後に応答の max-age が設定されます。

Location のオプションである AnyClient は、Cache-Control ヘッダー値の publicprivate にそれぞれ変換されます。 「NoStore と Location.None」セクションで説明したように、LocationNone に設定すると、Cache-Control および Pragma ヘッダーは両方とも no-cache に設定されます。

Location.Any (Cache-Controlpublic に設定された) は、"クライアントまたは任意の中間プロキシ" が値をキャッシュできることを示します。これには、応答キャッシュ ミドルウェアが含まれます。

Location.Client (Cache-Controlprivate に設定された) は、"クライアントのみ" が値をキャッシュできることを示します。 応答キャッシュ ミドルウェアを含め、中間キャッシュでは値をキャッシュしないようにします。

キャッシュ 制御ヘッダーは、応答をキャッシュするタイミングと方法について、クライアントと中間プロキシにガイダンスを提供します。 クライアントとプロキシが RFC 9111: HTTP キャッシュを遵守する保証はありません。 応答キャッシュ ミドルウェアは、仕様に定められたキャッシュ規則に常に従います。

次の例は、 を設定 Duration して既定値 Location のままにすることで生成されるヘッダーを示しています。

[Route("api/[controller]/ms")]
[HttpGet]
[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public ContentResult GetTimeMS() => Content(
                  DateTime.Now.Millisecond.ToString());

上記のコードには、応答に次のヘッダーが含まれています。

Cache-Control: public,max-age=10

キャッシュ プロファイル

多くのコントローラー アクション属性で応答キャッシュ設定を複製する代わりに、MVC/Razor Pages を設定するときにキャッシュ プロファイルをオプションとして構成できます。 参照されているキャッシュ プロファイルに見つかった値は、ResponseCacheAttribute で既定値として使用され、属性に指定されたプロパティによってオーバーライドされます。

次の例は、30 秒のキャッシュ プロファイルを示しています。

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCaching();
builder.Services.AddControllers(options =>
{
    options.CacheProfiles.Add("Default30",
        new CacheProfile()
        {
            Duration = 30
        });
});

var app = builder.Build();

app.UseHttpsRedirection();

// UseCors must be called before UseResponseCaching
//app.UseCors();

app.UseResponseCaching();

app.UseAuthorization();

app.MapControllers();

app.Run();

次のコードは、キャッシュ プロファイルを Default30 参照します。

[ApiController]
[ResponseCache(CacheProfileName = "Default30")]
public class Time2Controller : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

    [Route("api/[controller]/ticks")]
    [HttpGet]
    public ContentResult GetTimeTicks() => Content(
                      DateTime.Now.Ticks.ToString());
}

キャッシュ プロファイルによる結果のヘッダー応答には、次のものが Default30 含まれます。

Cache-Control: public,max-age=30

[ResponseCache] 属性は、次のものに適用できます。

  • Razor Pages: 属性をハンドラー メソッドに適用することはできません。 UI アプリで使用されるブラウザーは、応答キャッシュを防止します。
  • MVC コントローラー。
  • MVC アクション メソッド: メソッド レベルの属性は、クラス レベルの属性で指定された設定をオーバーライドします。

次のコードは、 [ResponseCache] コントローラー レベルとメソッド レベルで 属性を適用します。

[ApiController]
[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Time4Controller : ControllerBase
{
    [Route("api/[controller]")]
    [HttpGet]
    public ContentResult GetTime() => Content(
                      DateTime.Now.Millisecond.ToString());

    [Route("api/[controller]/ticks")]
    [HttpGet]
    public ContentResult GetTimeTicks() => Content(
                  DateTime.Now.Ticks.ToString());

    [Route("api/[controller]/ms")]
    [HttpGet]
    [ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
    public ContentResult GetTimeMS() => Content(
                      DateTime.Now.Millisecond.ToString());
}

その他の技術情報

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

応答キャッシュを使用すると、クライアントまたはプロキシから Web サーバーに対して行う要求の数が減ります。 応答キャッシュを使用することで、Web サーバーで応答を生成するために実行される作業量も減ります。 応答キャッシュは、クライアント、プロキシ、ミドルウェアで応答をどのようにキャッシュするかを指定するヘッダーによって制御されます。

[ResponseCache] 、応答キャッシュ ヘッダーの設定に関与します。 クライアントと中間プロキシでは、 RFC 9111: HTTP キャッシュに基づく応答をキャッシュするためのヘッダーを使用する必要があります。

HTTP 1.1 キャッシュ仕様に従うサーバー側キャッシュのためには、応答キャッシュ ミドルウェアを使用します。 ミドルウェアでは、 プロパティを [ResponseCache] 使用してサーバー側キャッシュ ヘッダーを設定できます。

HTTP ベースの応答キャッシュ

RFC 9111: HTTP キャッシュ では、インターネット キャッシュの動作について説明します。 キャッシュのために使用される主な HTTP ヘッダーは、Cache-Control です。これは、キャッシュの "ディレクティブ" を指定するために使用されます。 ディレクティブは、クライアントからサーバーに要求が送られるとき、さらにサーバーからクライアントに応答が返されるときのキャッシュの動作を制御します。 要求と応答はプロキシ サーバー間を移動し、プロキシ サーバーも HTTP 1.1 キャッシュ仕様に準拠している必要があります。

一般的な Cache-Control ディレクティブを次の表に示します。

ディレクティブ アクション
public キャッシュに応答を格納できます。
private 共有キャッシュによる応答の格納は禁止されます。 プライベート キャッシュに応答を格納し、再利用することができます。
max-age クライアントは、経過時間が指定の秒数を超えた応答を受け入れません。 例: max-age=60 (60 秒)、max-age=2592000 (1 か月)
no-cache 要求時: キャッシュに格納された応答を、要求を満たすために使用することはできません。 オリジン サーバーはクライアントに対する応答を再生成し、キャッシュ内に格納されている応答がミドルウェアによって更新されます。

応答時: オリジン サーバー上での検証なしに後続の要求に応答を使用することはできません。
no-store 要求時: キャッシュに要求を格納することは禁止されます。

応答時: キャッシュに応答を一部でも格納することは禁止されます。

キャッシュで役割を果たすその他のキャッシュ ヘッダーを次の表に示します。

ヘッダー 機能
Age オリジン サーバーで応答が生成されたか正常に検証されてから以降の推定時間 (秒単位)。
Expires それより後は応答が古いと見なされる日時。
Pragma no-cache 動作を設定する場合の HTTP/1.0 キャッシュとの下位互換性を確保するために存在します。 Cache-Control ヘッダーが存在する場合、Pragma ヘッダーは無視されます。
Vary キャッシュされた応答の最初要求と新しい要求の両方で、すべての Vary ヘッダー フィールドが一致しない限り、キャッシュされた応答を送信してはならないことを指定します。

HTTP ベースのキャッシュで要求の Cache-Control ディレクティブに従う

RFC 9111: HTTP キャッシュ (セクション 5.2.Cache-Control) には、クライアントから送信された有効なヘッダーを優先するキャッシュが必要です Cache-Control 。 クライアントは、no-cache ヘッダー値を使用して要求を行うことで、すべての要求に対してサーバーに新しい応答を強制的に生成させることができます。

HTTP キャッシュの目標を考えると、クライアントの Cache-Control 要求ヘッダーに常に従うことは理にかなっています。 公式仕様では、キャッシュはクライアント、プロキシ、およびサーバーのネットワーク全体で要求を満たすための待機時間とネットワーク オーバーヘッドを削減することを目的としています。 これは必ずしもオリジン サーバーの負荷を制御する方法ではありません。

応答キャッシュ ミドルウェアを使用する場合、このキャッシュ動作を開発者が制御することはできません。ミドルウェアは公式のキャッシュ仕様に準拠しているためです。 サーバーの負荷をより適切に制御するための "出力キャッシュ" のサポートは、ASP.NET Core の今後のリリースに向けての設計提案となっています。 詳細については、出力キャッシュのサポートの追加 (dotnet/aspnetcore #27387)に関するページを参照してください。

ASP.NET Core のその他のキャッシュ テクノロジ

メモリ内キャッシュ

メモリ内キャッシュの場合、キャッシュされるデータはサーバー メモリを使用して格納されます。 この種類のキャッシュは、セッション アフィニティを使用する単一サーバーまたは複数のサーバーに適しています。 セッション アフィニティは 、スティッキー セッションとも呼ばれます。 セッション アフィニティは、クライアントからの要求が常に処理のために同じサーバーにルーティングされることを意味します。

詳細については、「ASP.NET Coreのメモリ内キャッシュ」および「Azure Application Gatewayセッション アフィニティの問題のトラブルシューティング」を参照してください。

分散キャッシュ

アプリがクラウドまたはサーバー ファームでホストされている場合にデータをメモリに格納するには、分散キャッシュを使用します。 このキャッシュは、要求を処理するサーバー間で共有されます。 クライアントのためのキャッシュされたデータが使用可能な場合、クライアントから送信された要求は、グループ内の任意のサーバーで処理できます。 ASP.NET Core は、SQL Server、RedisNCache の分散キャッシュと連携して動作します。

詳細については、「ASP.NET Core の分散キャッシュ」を参照してください。

キャッシュ タグ ヘルパー

キャッシュ タグ ヘルパーを使用して、MVC ビューまたは Razor ページからのコンテンツをキャッシュします。 キャッシュ タグ ヘルパーは、メモリ内キャッシュを使用してデータを格納します。

詳細については、「ASP.NET Core MVC のキャッシュ タグ ヘルパー」を参照してください。

分散キャッシュ タグ ヘルパー

分散キャッシュ タグ ヘルパーを使用して、分散クラウドまたは Web ファームのシナリオで MVC ビューまたは Razor ページからのコンテンツをキャッシュします。 分散キャッシュ タグ ヘルパーは、SQL Server、Redis、または NCache を使用してデータを格納します。

詳細については、「ASP.NET Coreの分散キャッシュ タグ ヘルパー」を参照してください。

ResponseCache 属性

ResponseCacheAttribute は、応答キャッシュで適切なヘッダーを設定するために必要なパラメーターを指定します。

警告

認証されたクライアントに関する情報を含むコンテンツのキャッシュを無効にします。 キャッシュは、ユーザーの ID またはユーザーがサインイン済みかどうかに基づいて変更されることのないコンテンツに対してのみ有効にする必要があります。

VaryByQueryKeys は、指定されたクエリ キーの一覧の値によって、格納された応答を変化させます。 * の単一の値が指定されている場合、応答はミドルウェアによって、すべての要求クエリ文字列パラメーターに応じて変化させられます。

VaryByQueryKeys プロパティを設定するには、応答キャッシュ ミドルウェアを有効にする必要があります。 そうしないと、ランタイム例外がスローされます。 VaryByQueryKeys プロパティに対応する HTTP ヘッダーは存在しません。 このプロパティは、応答キャッシュ ミドルウェアによって処理される HTTP 機能です。 キャッシュされた応答をミドルウェアで処理するには、クエリ文字列とクエリ文字列値が前の要求と一致する必要があります。 たとえば、次の表に示す一連の要求と結果について考えてみます。

Request 結果
http://example.com?key1=value1 サーバーから返されます。
http://example.com?key1=value1 ミドルウェアから返されます。
http://example.com?key1=value2 サーバーから返されます。

最初の要求はサーバーによって返され、ミドルウェアにキャッシュされます。 2 番目の要求は、クエリ文字列が前の要求と一致するため、ミドルウェアによって返されます。 3 番目の要求は、クエリ文字列の値が前の要求と一致しないため、ミドルウェア キャッシュ内に存在しません。

ResponseCacheAttribute は、(IFilterFactory を使用して) Microsoft.AspNetCore.Mvc.Internal.ResponseCacheFilter を構成および作成するために使用されます。 ResponseCacheFilter は、応答の適切な HTTP ヘッダーと機能を更新する処理を実行します。 フィルターにより次のことが行われます。

  • VaryCache-ControlPragmaの既存ヘッダーがあれば削除します。
  • ResponseCacheAttribute で設定されたプロパティに基づいて、適切なヘッダーを書き出します。
  • VaryByQueryKeys が設定されている場合は、応答キャッシュの HTTP 機能を更新します。

Vary

このヘッダーは、VaryByHeader プロパティが設定されている場合にのみ書き込まれます。 そのプロパティは Vary プロパティの値に設定されます。 次のサンプルでは、VaryByHeader プロパティを使用しています。

[ResponseCache(VaryByHeader = "User-Agent", Duration = 30)]
public class Cache1Model : PageModel
{

サンプル アプリを使用して、ブラウザーのネットワーク ツールで応答ヘッダーを表示します。 次の応答ヘッダーは、Cache1 ページの応答と共に送信されます。

Cache-Control: public,max-age=30
Vary: User-Agent

NoStore および Location.None

NoStore は、他のほとんどのプロパティをオーバーライドします。 このプロパティを true に設定すると、Cache-Control ヘッダーが no-store に設定されます。 LocationNone に設定すると、次のようになります。

  • Cache-Controlno-store,no-cache に設定されます。
  • Pragmano-cache に設定されます。

NoStorefalseLocationNone の場合、Cache-ControlPragmano-cache に設定されます。

NoStore は通常、エラー ページに対して true に設定されます。 サンプル アプリの Cache2 ページでは、応答を格納しないようにクライアントに指示する応答ヘッダーが生成されます。

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class Cache2Model : PageModel
{

サンプル アプリは、次のヘッダーを含む Cache2 ページを返します。

Cache-Control: no-store,no-cache
Pragma: no-cache

アプリのすべての MVC コントローラーまたはRazorページ ページ応答に を適用ResponseCacheAttributeするには、MVC フィルターまたは Razor Pages フィルターを使用して追加します。

MVC アプリの場合:

services.AddMvc().AddMvcOptions(options => 
    options.Filters.Add(
        new ResponseCacheAttribute
        {
            NoStore = true, 
            Location = ResponseCacheLocation.None
        }));

Pages アプリに Razor 適用される方法については、「 MVC グローバル フィルター リストへの追加 ResponseCacheAttribute は Pages に適用 Razor されません (dotnet/aspnetcore #18890)」を参照してください。

Location と Duration

キャッシュを有効にするには、Duration を正の値に設定し、LocationAny (既定値) または Client にする必要があります。 フレームワークによって、Cache-Control ヘッダーが location 値に設定され、その後に応答の max-age が設定されます。

Location のオプションである AnyClient は、Cache-Control ヘッダー値の publicprivate にそれぞれ変換されます。 「NoStore と Location.None」セクションで説明したように、LocationNone に設定すると、Cache-Control および Pragma ヘッダーは両方とも no-cache に設定されます。

Location.Any (Cache-Controlpublic に設定された) は、"クライアントまたは任意の中間プロキシ" が値をキャッシュできることを示します。これには、応答キャッシュ ミドルウェアが含まれます。

Location.Client (Cache-Controlprivate に設定された) は、"クライアントのみ" が値をキャッシュできることを示します。 応答キャッシュ ミドルウェアを含め、中間キャッシュでは値をキャッシュしないようにします。

キャッシュ制御ヘッダーは、いつどのように応答をキャッシュするかについてのガイダンスをクライアントと中間プロキシに提供するだけです。 クライアントとプロキシが RFC 9111: HTTP キャッシュを遵守するという保証はありません。 応答キャッシュ ミドルウェアは、仕様に定められたキャッシュ規則に常に従います。

次の例は、サンプル アプリの Cache3 ページ モデルと、Duration を設定し、既定の Location 値をそのまま使用して生成されたヘッダーを示しています。

[ResponseCache(Duration = 10, Location = ResponseCacheLocation.Any, NoStore = false)]
public class Cache3Model : PageModel
{

サンプル アプリからは、次のヘッダーを含む Cache3 ページが返されます。

Cache-Control: public,max-age=10

キャッシュ プロファイル

多くのコントローラー アクション属性で応答キャッシュ設定を複製するのではなく、Startup.ConfigureServices で MVC または Razor Pages を設定するときに、キャッシュ プロファイルをオプションとして構成できます。 参照されているキャッシュ プロファイルに見つかった値は、ResponseCacheAttribute で既定値として使用され、属性に指定されたプロパティによってオーバーライドされます。

キャッシュ プロファイルを設定します。 次の例は、サンプル アプリの Startup.ConfigureServices での 30 秒のキャッシュ プロファイルを示しています。

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddMvc(options =>
    {
        options.CacheProfiles.Add("Default30",
            new CacheProfile()
            {
                Duration = 30
            });
    });
}

サンプル アプリの Cache4 ページ モデルは、Default30 キャッシュ プロファイルを参照します。

[ResponseCache(CacheProfileName = "Default30")]
public class Cache4Model : PageModel
{

ResponseCacheAttribute は以下に対して適用できます。

  • Razor Pages: 属性をハンドラー メソッドに適用することはできません。
  • MVC コントローラー。
  • MVC アクション メソッド: メソッド レベルの属性は、クラス レベルの属性で指定された設定をオーバーライドします。

結果として、Default30 キャッシュ プロファイルによって Cache4 ページの応答に適用されるヘッダーは、次のようになります。

Cache-Control: public,max-age=30

その他の技術情報