ASP.NET Core での応答キャッシュ ミドルウェア

作成者: John Luo および Rick Anderson

この記事では、ASP.NET Core アプリで応答キャッシュ ミドルウェアを構成する方法について説明します。 このミドルウェアでは、応答をキャッシュ可能にするタイミングを決定し、応答を格納して、キャッシュからの応答を提供します。 HTTP キャッシュの概要と [ResponseCache] 属性については、「応答キャッシュ」を参照してください。

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

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

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

構成

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

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseHttpsRedirection();

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

app.UseResponseCaching();

警告

CORS ミドルウェアを使用する場合、UseResponseCaching の前に UseCors を呼び出す必要があります。

サンプル アプリでは、後続の要求でキャッシュを制御するヘッダーを追加します。

  • Cache-Control: 最大 10 秒間、キャッシュ可能な応答をキャッシュします。
  • Vary: 後続の要求の Accept-Encoding ヘッダーが元の要求のヘッダーと一致する場合にのみ、キャッシュされた応答を提供するようにミドルウェアを構成します。
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseHttpsRedirection();

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

app.UseResponseCaching();

app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl =
        new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = TimeSpan.FromSeconds(10)
        };
    context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] =
        new string[] { "Accept-Encoding" };

    await next();
});

app.MapGet("/", () => DateTime.Now.Millisecond);

app.Run();

上記のヘッダーは応答に書き込まれず、コントローラー、アクション、または Razor ページの場合はオーバーライドされます。

  • [ResponseCache] 属性を含みます。 これは、プロパティが設定されていない場合でも当てはまります。 たとえば、VaryByHeader プロパティを省略すると、対応するヘッダーが応答から削除されます。

応答キャッシュ ミドルウェアでは、200 (OK) 状態コードを生成するサーバー応答のみがキャッシュされます。 エラー ページ を含む他の応答は、ミドルウェアによって無視されます。

警告

認証されたクライアントのコンテンツを含む応答は、ミドルウェアによって保存および提供されないように、キャッシュ不可としてマークする必要があります。 応答がキャッシュ可能であるかどうかをミドルウェアで判断する方法の詳細については、「キャッシュの条件」を参照してください。

上記のコードは通常、キャッシュされた値をブラウザーに返しません。 FiddlerPostman、または要求ヘッダーを明示的に設定でき、キャッシュのテストに適した別のツールを使用します。 詳細については、この記事の「トラブルシューティング」を参照してください。

[オプション]

応答キャッシュのオプションを次の表に示します。

オプション 説明
MaximumBodySize 応答本文の最大キャッシュ可能サイズ (バイト単位)。 既定値は、64 * 1024 * 1024 (64 MB) です。
SizeLimit 応答キャッシュ ミドルウェアのサイズ制限 (バイト単位)。 既定値は、100 * 1024 * 1024 (100 MB) です。
UseCaseSensitivePaths 大文字と小文字を区別するパスに応答をキャッシュするかどうかを決定します。 既定値は false です。

次の例では、ミドルウェアを次のように構成します。

  • 本文のサイズが 1,024 バイト以下の応答をキャッシュします。
  • 大文字と小文字を区別するパスで応答を保存します。 たとえば、/page1/Page1 は別個に格納されます。
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCaching(options =>
{
    options.MaximumBodySize = 1024;
    options.UseCaseSensitivePaths = true;
});

var app = builder.Build();

app.UseHttpsRedirection();

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

app.UseResponseCaching();

app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl =
        new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = TimeSpan.FromSeconds(10)
        };
    context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] =
        new string[] { "Accept-Encoding" };

    await next(context);
});

app.MapGet("/", () => DateTime.Now.Millisecond);

app.Run();

VaryByQueryKeys

MVC、Web API コントローラー、または Razor ページのページ モデルを使用する場合、[ResponseCache] 属性では、応答キャッシュの適切なヘッダーを設定するために必要なパラメーターを指定します。 ミドルウェアを厳密に必要とする [ResponseCache] 属性のパラメーターは、VaryByQueryKeys のみです。これは、実際の HTTP ヘッダーに対応しません。 詳細については、「ASP.NET Core の応答キャッシュ」を参照してください。

[ResponseCache] 属性を使用しない場合、応答キャッシュは、VaryByQueryKeys に応じて異なることがあります。 HttpContext.Featuresから直接 ResponseCachingFeature を使用します。

var responseCachingFeature = context.HttpContext.Features.Get<IResponseCachingFeature>();

if (responseCachingFeature != null)
{
    responseCachingFeature.VaryByQueryKeys = new[] { "MyKey" };
}

VaryByQueryKeys* に等しい単一の値を使用すると、キャッシュは、すべての要求クエリ パラメーターによって異なります。

応答キャッシュ ミドルウェアで使用される HTTP ヘッダー

次の表では、応答キャッシュに影響を与える HTTP ヘッダーについて説明します。

ヘッダー 詳細
Authorization このヘッダーがある場合、応答はキャッシュされません。
Cache-Control ミドルウェアでは、public キャッシュ ディレクティブでマークされたキャッシュ応答のみが考慮されます。 次のパラメーターを使用してキャッシュを制御します。
  • max-age
  • max-stale†
  • min-fresh
  • must-revalidate
  • no-cache
  • no-store
  • only-if-cached
  • プライベート
  • public
  • s-maxage
  • proxy-revalidate‡
max-staleに制限を指定しない場合、ミドルウェアはアクションを実行しません。
proxy-revalidate には、must-revalidate と同じ効果があります。

詳細については、「RFC 9111: 要求ディレクティブ」を参照してください。
Pragma 要求内の Pragma: no-cache ヘッダーは、Cache-Control: no-cache と同じ効果を生成します。 このヘッダーは、Cache-Control ヘッダーがある場合、その中の関連するディレクティブによってオーバーライドされます。 HTTP/1.0 との下位互換性が考慮されます。
Set-Cookie このヘッダーがある場合、応答はキャッシュされません。 1 つ以上の cookie を設定する要求処理パイプライン内のミドルウェアは、応答キャッシュ ミドルウェアによって応答 (たとえば、cookie ベースの TempData プロバイダー) がキャッシュされるのを防ぎます。
Vary Vary ヘッダーは、キャッシュされた応答を別のヘッダーで変更するために使用されます。 たとえば、Vary: Accept-Encoding ヘッダーを含めてエンコードすることによって応答をキャッシュします。これにより、ヘッダー Accept-Encoding: gzipAccept-Encoding: text/plain を別々に持つ要求の応答がキャッシュされます。 ヘッダー値 * を持つ応答が格納されることはありません。
Expires このヘッダーによって古くなったと見なされた応答は、他の Cache-Control ヘッダーによってオーバーライドされない限り、保存または取得されません。
If-None-Match 値が * ではなく、応答の ETag が指定された値のいずれとも一致しない場合、キャッシュから完全な応答が提供されます。 それ以外の場合、304 (変更なし) の応答が提供されます。
If-Modified-Since If-None-Match ヘッダーがない場合、キャッシュされた応答の日付が指定された値よりも新しい場合は、キャッシュから完全な応答が提供されます。 それ以外の場合は、"304 (変更なし)" の応答が処理されます。
Date キャッシュから提供される際、Date ヘッダーは、元の応答で提供されなかった場合にミドルウェアによって設定されます。
Content-Length キャッシュから提供される際、Content-Length ヘッダーは、元の応答で提供されなかった場合にミドルウェアによって設定されます。
Age 元の応答で送信された Age ヘッダーは無視されます。 ミドルウェアでは、キャッシュされた応答を提供するときに新しい値を計算します。

要求キャッシュ制御ディレクティブを尊重するキャッシュ

ミドルウェアはルール RFC 9111: HTTP のキャッシュ (セクション 5.2. Cache-Control) を遵守します。 この規則では、クライアントによって送信された有効な Cache-Control ヘッダーを尊重するためにキャッシュが必要です。 この仕様では、クライアントは、no-cache ヘッダー値を使用して要求を行い、サーバーに対して、要求ごとに新しい応答を生成するように強制できます。 現在、ミドルウェアは公式のキャッシュ仕様に準拠しているため、ミドルウェアを使用する場合、開発者はこのキャッシュ動作を制御できません。

キャッシュの動作をより細かく制御するには、ASP.NET Core の他のキャッシュ機能を調べます。 次のトピックを参照してください。

トラブルシューティング

応答キャッシュ ミドルウェアでは IMemoryCache を使用します。これは容量が限られています。 容量を超えると、メモリ キャッシュが圧縮されます

キャッシュ動作が期待どおりではない場合は、応答がキャッシュ可能であり、キャッシュから提供できることを確認します。 要求の受信ヘッダーと応答の送信ヘッダーを調べます。 デバッグに役立つように、ログを有効にします。

キャッシュ動作をテストしてトラブルシューティングする場合、通常、ブラウザーはキャッシュを妨げる要求ヘッダーを設定します。 たとえば、ブラウザーでは、ページを更新するときにCache-Control ヘッダーを no-cacheまたは max-age=0 に設定する場合があります。 FiddlerPostman およびその他ツールでは、要求ヘッダーを明示的に設定でき、キャッシュのテストに適しています。

キャッシュの条件

  • 要求によって、200 (OK) 状態コードでサーバー応答が生成される必要があります。
  • 要求メソッドは、GET または HEAD である必要があります。
  • キャッシュを必要とするミドルウェアの前に、応答キャッシュ ミドルウェアを配置する必要があります。 詳細については、「ASP.NET Core のミドルウェア」を参照してください。
  • Authorization ヘッダーは存在してはなりません。
  • Cache-Control ヘッダー パラメーターは有効である必要があり、応答は、public としてマークされる必要があり、privateとしてマークすることはできません。
  • Cache-Control ヘッダーが存在しない場合は、Pragma: no-cache ヘッダーは存在してはなりません。これは、Cache-Control ヘッダーが存在する場合、Pragma ヘッダーがオーバーライドされるためです。
  • Set-Cookie ヘッダーは存在してはなりません。
  • Vary ヘッダー パラメーターは有効で、* と等しくない必要があります。
  • Content-Length ヘッダー値 (設定されている場合) は、応答本文のサイズと一致する必要があります。
  • IHttpSendFileFeature は使用されません。
  • 応答は、Expires ヘッダーと max-age および s-maxageキャッシュ ディレクティブで指定された古いものであってはなりません。
  • 応答バッファーリングは成功させる必要があります。 応答のサイズは、構成済みまたは既定の SizeLimit より小さくする必要があります。 応答の本文のサイズは、構成済みまたは既定の MaximumBodySize より小さくする必要があります。
  • 応答は RFC 9111: HTTP キャッシュ に従ってキャッシュ可能である必要があります。 たとえば、no-store ディレクティブは、要求または応答ヘッダー フィールドに存在してはなりません。 詳細については、 「RFC 9111: HTTP キャッシュ (セクション 3: キャッシュへの応答の格納」を参照してください。

Note

クロスサイト リクエスト フォージェリ (CSRF) 攻撃を防ぐためにセキュリティで保護されたトークンを生成するための偽造防止システムは、応答がキャッシュされないように、Cache-Control ヘッダーと Pragma ヘッダーを no-cache に設定します。 HTML フォーム要素の偽造防止トークンを無効にする方法については、「ASP.NET Core でのクロスサイト リクエスト フォージェリ (XSRF/CSRF) 攻撃の防止」を参照してください。

その他のリソース

この記事では、ASP.NET Core アプリで応答キャッシュ ミドルウェアを構成する方法について説明します。 このミドルウェアでは、応答をキャッシュ可能にするタイミングを決定し、応答を格納して、キャッシュからの応答を提供します。 HTTP キャッシュの概要と [ResponseCache] 属性については、「応答キャッシュ」を参照してください。

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

構成

応答キャッシュ ミドルウェアは、共有フレームワークを介して ASP.NET Core アプリで暗黙的に使用できます。

Startup.ConfigureServices で、応答キャッシュ ミドルウェアをサービス コレクションに追加します。

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCaching();
    services.AddRazorPages();
}

UseResponseCaching 拡張メソッドでこのミドルウェアを使用するようにアプリを構成します。このメソッドは、ミドルウェアを Startup.Configure 内の要求処理パイプラインに追加します。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();
    app.UseRouting();
    // UseCors must be called before UseResponseCaching
    // app.UseCors("myAllowSpecificOrigins");

    app.UseResponseCaching();

    app.Use(async (context, next) =>
    {
        context.Response.GetTypedHeaders().CacheControl = 
            new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
            {
                Public = true,
                MaxAge = TimeSpan.FromSeconds(10)
            };
        context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = 
            new string[] { "Accept-Encoding" };

        await next();
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

警告

CORS ミドルウェアを使用する場合、UseResponseCaching の前に UseCors を呼び出す必要があります。

サンプル アプリでは、後続の要求でキャッシュを制御するヘッダーを追加します。

  • Cache-Control: 最大 10 秒間、キャッシュ可能な応答をキャッシュします。
  • Vary: 後続の要求の Accept-Encoding ヘッダーが元の要求のヘッダーと一致する場合にのみ、キャッシュされた応答を提供するようにミドルウェアを構成します。
// using Microsoft.AspNetCore.Http;

app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl = 
        new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = TimeSpan.FromSeconds(10)
        };
    context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = 
        new string[] { "Accept-Encoding" };

    await next();
});

上記のヘッダーは応答に書き込まれず、コントローラー、アクション、または Razor ページの場合はオーバーライドされます。

  • [ResponseCache] 属性を含みます。 これは、プロパティが設定されていない場合でも当てはまります。 たとえば、VaryByHeader プロパティを省略すると、対応するヘッダーが応答から削除されます。

応答キャッシュ ミドルウェアでは、200 (OK) 状態コードを生成するサーバー応答のみがキャッシュされます。 エラー ページ を含む他の応答は、ミドルウェアによって無視されます。

警告

認証されたクライアントのコンテンツを含む応答は、ミドルウェアによって保存および提供されないように、キャッシュ不可としてマークする必要があります。 応答がキャッシュ可能であるかどうかをミドルウェアで判断する方法の詳細については、「キャッシュの条件」を参照してください。

[オプション]

応答キャッシュのオプションを次の表に示します。

オプション 説明
MaximumBodySize 応答本文の最大キャッシュ可能サイズ (バイト単位)。 既定値は、64 * 1024 * 1024 (64 MB) です。
SizeLimit 応答キャッシュ ミドルウェアのサイズ制限 (バイト単位)。 既定値は、100 * 1024 * 1024 (100 MB) です。
UseCaseSensitivePaths 大文字と小文字を区別するパスに応答をキャッシュするかどうかを決定します。 既定値は false です。

次の例では、ミドルウェアを次のように構成します。

  • 本文のサイズが 1,024 バイト以下の応答をキャッシュします。
  • 大文字と小文字を区別するパスで応答を保存します。 たとえば、/page1/Page1 は別個に格納されます。
services.AddResponseCaching(options =>
{
    options.MaximumBodySize = 1024;
    options.UseCaseSensitivePaths = true;
});

VaryByQueryKeys

MVC または Web API コントローラー、またはRazor ページのページ モデルを使用する場合、[ResponseCache] 属性では、応答キャッシュの適切なヘッダーを設定するために必要なパラメーターを指定します。 ミドルウェアを厳密に必要とする [ResponseCache] 属性のパラメーターは、VaryByQueryKeys のみです。これは、実際の HTTP ヘッダーに対応しません。 詳細については、「ASP.NET Core の応答キャッシュ」を参照してください。

[ResponseCache] 属性を使用しない場合、応答キャッシュは、VaryByQueryKeys に応じて異なることがあります。 HttpContext.Featuresから直接 ResponseCachingFeature を使用します。

var responseCachingFeature = context.HttpContext.Features.Get<IResponseCachingFeature>();

if (responseCachingFeature != null)
{
    responseCachingFeature.VaryByQueryKeys = new[] { "MyKey" };
}

VaryByQueryKeys* に等しい単一の値を使用すると、キャッシュは、すべての要求クエリ パラメーターによって異なります。

応答キャッシュ ミドルウェアで使用される HTTP ヘッダー

次の表では、応答キャッシュに影響を与える HTTP ヘッダーについて説明します。

ヘッダー 詳細
Authorization このヘッダーがある場合、応答はキャッシュされません。
Cache-Control ミドルウェアでは、public キャッシュ ディレクティブでマークされたキャッシュ応答のみが考慮されます。 次のパラメーターを使用してキャッシュを制御します。
  • max-age
  • max-stale†
  • min-fresh
  • must-revalidate
  • no-cache
  • no-store
  • only-if-cached
  • プライベート
  • public
  • s-maxage
  • proxy-revalidate‡
max-staleに制限を指定しない場合、ミドルウェアはアクションを実行しません。
proxy-revalidate には、must-revalidate と同じ効果があります。

詳細については、「RFC 9111: 要求ディレクティブ」を参照してください。
Pragma 要求内の Pragma: no-cache ヘッダーは、Cache-Control: no-cache と同じ効果を生成します。 このヘッダーは、Cache-Control ヘッダーがある場合、その中の関連するディレクティブによってオーバーライドされます。 HTTP/1.0 との下位互換性が考慮されます。
Set-Cookie このヘッダーがある場合、応答はキャッシュされません。 1 つ以上の cookie を設定する要求処理パイプライン内のミドルウェアは、応答キャッシュ ミドルウェアによって応答 (たとえば、cookie ベースの TempData プロバイダー) がキャッシュされるのを防ぎます。
Vary Vary ヘッダーは、キャッシュされた応答を別のヘッダーで変更するために使用されます。 たとえば、Vary: Accept-Encoding ヘッダーを含めてエンコードすることによって応答をキャッシュします。これにより、ヘッダー Accept-Encoding: gzipAccept-Encoding: text/plain を別々に持つ要求の応答がキャッシュされます。 ヘッダー値 * を持つ応答が格納されることはありません。
Expires このヘッダーによって古くなったと見なされた応答は、他の Cache-Control ヘッダーによってオーバーライドされない限り、保存または取得されません。
If-None-Match 値が * ではなく、応答の ETag が指定された値のいずれとも一致しない場合、キャッシュから完全な応答が提供されます。 それ以外の場合、304 (変更なし) の応答が提供されます。
If-Modified-Since If-None-Match ヘッダーがない場合、キャッシュされた応答の日付が指定された値よりも新しい場合は、キャッシュから完全な応答が提供されます。 それ以外の場合は、"304 (変更なし)" の応答が処理されます。
Date キャッシュから提供される際、Date ヘッダーは、元の応答で提供されなかった場合にミドルウェアによって設定されます。
Content-Length キャッシュから提供される際、Content-Length ヘッダーは、元の応答で提供されなかった場合にミドルウェアによって設定されます。
Age 元の応答で送信された Age ヘッダーは無視されます。 ミドルウェアでは、キャッシュされた応答を提供するときに新しい値を計算します。

要求キャッシュ制御ディレクティブを尊重するキャッシュ

ミドルウェアはルール RFC 9111: HTTP のキャッシュ (セクション 5.2. Cache-Control) を遵守します。 この規則では、クライアントによって送信された有効な Cache-Control ヘッダーを尊重するためにキャッシュが必要です。 この仕様では、クライアントは、no-cache ヘッダー値を使用して要求を行い、サーバーに対して、要求ごとに新しい応答を生成するように強制できます。 現在、ミドルウェアは公式のキャッシュ仕様に準拠しているため、ミドルウェアを使用する場合、開発者はこのキャッシュ動作を制御できません。

キャッシュの動作をより細かく制御するには、ASP.NET Core の他のキャッシュ機能を調べます。 次のトピックを参照してください。

トラブルシューティング

キャッシュ動作が期待どおりではない場合は、応答がキャッシュ可能であり、キャッシュから提供できることを確認します。 要求の受信ヘッダーと応答の送信ヘッダーを調べます。 デバッグに役立つように、ログを有効にします。

キャッシュ動作をテストおよびトラブルシューティングする場合、ブラウザーでは、望ましくない方法でキャッシュに影響を与える要求ヘッダーが設定される可能性があります。 たとえば、ブラウザーでは、ページを更新するときにCache-Control ヘッダーを no-cacheまたは max-age=0 に設定する場合があります。 次のツールでは、要求ヘッダーを明示的に設定でき、キャッシュのテストに適しています。

キャッシュの条件

  • 要求によって、200 (OK) 状態コードでサーバー応答が生成される必要があります。
  • 要求メソッドは、GET または HEAD である必要があります。
  • Startup.Configure では、キャッシュを必要とするミドルウェアの前に、応答キャッシュ ミドルウェアを配置する必要があります。 詳細については、「ASP.NET Core のミドルウェア」を参照してください。
  • Authorization ヘッダーは存在してはなりません。
  • Cache-Control ヘッダー パラメーターは有効である必要があり、応答は、public としてマークされる必要があり、privateとしてマークすることはできません。
  • Cache-Control ヘッダーが存在しない場合は、Pragma: no-cache ヘッダーは存在してはなりません。これは、Cache-Control ヘッダーが存在する場合、Pragma ヘッダーがオーバーライドされるためです。
  • Set-Cookie ヘッダーは存在してはなりません。
  • Vary ヘッダー パラメーターは有効で、* と等しくない必要があります。
  • Content-Length ヘッダー値 (設定されている場合) は、応答本文のサイズと一致する必要があります。
  • IHttpSendFileFeature は使用されません。
  • 応答は、Expires ヘッダーと max-age および s-maxageキャッシュ ディレクティブで指定された古いものであってはなりません。
  • 応答バッファーリングは成功させる必要があります。 応答のサイズは、構成済みまたは既定の SizeLimit より小さくする必要があります。 応答の本文のサイズは、構成済みまたは既定の MaximumBodySize より小さくする必要があります。
  • 応答は RFC 9111: HTTP キャッシュ に従ってキャッシュ可能である必要があります。 たとえば、no-store ディレクティブは、要求または応答ヘッダー フィールドに存在してはなりません。 詳細については、 「RFC 9111: HTTP キャッシュ (セクション 3: キャッシュへの応答の格納」を参照してください。

Note

クロスサイト リクエスト フォージェリ (CSRF) 攻撃を防ぐためにセキュリティで保護されたトークンを生成するための偽造防止システムは、応答がキャッシュされないように、Cache-Control ヘッダーと Pragma ヘッダーを no-cache に設定します。 HTML フォーム要素の偽造防止トークンを無効にする方法については、「ASP.NET Core でのクロスサイト リクエスト フォージェリ (XSRF/CSRF) 攻撃の防止」を参照してください。

その他のリソース