Middleware de cache de resposta no ASP.NET Core

Por John Luo e Rick Anderson

Esse artigo explica como configurar o Middleware de Cache de Resposta em um aplicativo ASP.NET Core. O middleware determina quando as respostas são armazenáveis em cache, armazena respostas e fornece respostas do cache. Para obter uma introdução ao cache HTTP e ao atributo [ResponseCache], confira Cache de Resposta.

O middleware de cache de resposta:

  • Habilita o cache de respostas do servidor com base em cabeçalhos de cache HTTP. Implementa a semântica de cache HTTP padrão. Os caches baseados em cabeçalhos de cache HTTP, assim como fazem os proxies.
  • Normalmente, não é benéfico para aplicativos de interface do usuário, como o Razor Pages, porque os navegadores geralmente definem cabeçalhos de solicitação que impedem o cache. O cache de saída, que está disponível no ASP.NET Core 7.0 e posterior, beneficia os aplicativos de interface do usuário. Com o cache de saída, a configuração decide o que deve ser armazenado em cache independentemente dos cabeçalhos HTTP.
  • Pode ser benéfico para solicitações públicas de API GET ou HEAD de clientes, desde que as Condições em cache para o armazenamento sejam atendidas.

Para testar o cache de resposta, use Fiddler ou outra ferramenta que possa definir explicitamente os cabeçalhos de solicitação. A configuração explícita de cabeçalhos é preferida para testar o armazenamento em cache. Para saber mais, consulte a Solução de problemas.

Configuração

No Program.cs, adicione os serviços middleware de cache de resposta AddResponseCaching à coleção de serviços e configure o aplicativo para usar o middleware com o método de extensão UseResponseCaching. UseResponseCaching adiciona o middleware ao pipeline de processamento de solicitações:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCaching();

var app = builder.Build();

app.UseHttpsRedirection();

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

app.UseResponseCaching();

Aviso

UseCors deve ser chamado antes de UseResponseCaching ao usar o middleware CORS.

O aplicativo de exemplo adiciona cabeçalhos para controlar o cache nas solicitações seguintes:

  • Cache-Control: armazena em cache respostas armazenáveis em cache por até 10 segundos.
  • Vary: configura o middleware para atender a uma resposta armazenada em cache somente se o cabeçalho Accept-Encoding das solicitações seguintes corresponder ao da solicitação original.
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();

Os cabeçalhos anteriores não são gravados na resposta e são substituídos quando um controlador, ação ou Página Razor:

  • Tiver um atributo [ResponseCache]. Isso se aplica mesmo que uma propriedade não esteja definida. Por exemplo, omitir a propriedade VaryByHeader fará com que o cabeçalho correspondente seja removido da resposta.

O Middleware de Cache de Resposta armazena em cache apenas as respostas do servidor que resultam em um código de status 200 (OK). Todas as outras respostas, incluindo páginas de erro, são ignoradas pelo middleware.

Aviso

As respostas que contêm conteúdo para clientes autenticados devem ser marcadas como não armazenáveis em cache para impedir que o middleware armazene e forneça essas respostas. Confira Condições de cache para obter detalhes sobre como o middleware determina se uma resposta é armazenável em cache.

O código anterior normalmente não retorna um valor armazenado em cache para um navegador. Use o Fiddler, o Postman ou outra ferramenta que possa definir explicitamente cabeçalhos de solicitação e seja preferencial para testar o cache. Para obter mais informações, confira Solução de problemas neste artigo.

Opções

As opções de cache de resposta são mostradas na tabela a seguir.

Opção Descrição
MaximumBodySize O maior tamanho armazenável em cache para o corpo da resposta em bytes. O valor padrão é 64 * 1024 * 1024 (64 MB).
SizeLimit O limite de tamanho para o middleware de cache de resposta em bytes. O valor padrão é 100 * 1024 * 1024 (100 MB).
UseCaseSensitivePaths Determina se as respostas são armazenadas em cache em caminhos que diferenciam maiúsculas de minúsculas. O valor padrão é false.

O exemplo a seguir configura o middleware para:

  • Respostas de cache com um tamanho de corpo menor ou igual a 1.024 bytes.
  • Armazene as respostas por caminhos que diferenciam maiúsculas de minúsculas. Por exemplo, /page1 e /Page1 são armazenados separadamente.
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

Ao usar MVC, controladores de API Web ou os modelos de página de Páginas Razor, o atributo [ResponseCache] especifica os parâmetros necessários para definir os cabeçalhos apropriados para o cache de resposta. O único parâmetro do atributo [ResponseCache] que exige estritamente o middleware é VaryByQueryKeys, que não corresponde a um cabeçalho HTTP real. Para obter mais informações, confira Cache de resposta no ASP.NET Core.

Ao não usar o atributo [ResponseCache], o cache de resposta pode ser variado com VaryByQueryKeys. Use o ResponseCachingFeature diretamente do HttpContext.Features:

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

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

O uso de um único valor igual a * em VaryByQueryKeys varia o cache de acordo com todos os parâmetros de consulta de solicitação.

Cabeçalhos HTTP usados pelo Middleware de Cache de Resposta

A tabela a seguir fornece informações sobre cabeçalhos HTTP que afetam o cache de resposta.

parâmetro Detalhes
Authorization A resposta não será armazenada em cache se o cabeçalho existir.
Cache-Control O middleware considera apenas as respostas de cache marcadas com a diretiva de cache public. Controlar o cache com os seguintes parâmetros:
  • max-age
  • max-stale†
  • min-fresh
  • must-revalidate
  • no-cache
  • no-store
  • only-if-cached
  • particulares
  • públicos
  • s-maxage
  • proxy-revalidate‡
†Se nenhum limite for especificado para max-stale, o middleware não executará nenhuma ação.
proxy-revalidate tem o mesmo efeito que must-revalidate.

Para obter mais informações, confira RFC 9111: Diretivas de Solicitação.
Pragma Um cabeçalho Pragma: no-cache na solicitação produz o mesmo efeito que Cache-Control: no-cache. Esse cabeçalho é substituído pelas diretivas relevantes no cabeçalho Cache-Control, se presente. Considerado para compatibilidade com versões anteriores com HTTP/1.0.
Set-Cookie A resposta não será armazenada em cache se o cabeçalho existir. Qualquer middleware no pipeline de processamento de solicitações que defina um ou mais cookies impede que o Middleware de Cache de Resposta armazene em cache a resposta (por exemplo, o provedor TempData baseado em cookie).
Vary O cabeçalho Vary é usado para variar a resposta armazenada em cache por outro cabeçalho. Por exemplo, armazene respostas em cache codificando incluindo o cabeçalho Vary: Accept-Encoding, que armazena em cache respostas para solicitações com cabeçalhos Accept-Encoding: gzip e Accept-Encoding: text/plain separadamente. Uma resposta com um valor de cabeçalho de * nunca é armazenada.
Expires Uma resposta considerada obsoleta por esse cabeçalho não é armazenada nem recuperada, a menos que seja substituída por outros cabeçalhos Cache-Control.
If-None-Match A resposta completa é servida a partir do cache se o valor não for * e o ETag da resposta não corresponder a nenhum dos valores fornecidos. Caso contrário, uma resposta 304 (Não Modificada) será atendida.
If-Modified-Since Se o cabeçalho If-None-Match não estiver presente, uma resposta completa será atendida do cache se a data de resposta armazenada em cache for mais recente do que o valor fornecido. Caso contrário, uma resposta 304 – Não Modificada será atendida.
Date Ao servir do cache, o cabeçalho Date será definido pelo middleware se ele não tiver sido fornecido na resposta original.
Content-Length Ao servir do cache, o cabeçalho Content-Length será definido pelo middleware se ele não tiver sido fornecido na resposta original.
Age O cabeçalho Age enviado na resposta original é ignorado. O middleware calcula um novo valor ao servir uma resposta armazenada em cache.

O armazenamento em cache respeita as diretivas do Cache-Control da solicitação

O middleware respeita as regras do RFC 9111: Cache HTTP (Seção 5.2. Cache-Control). As regras exigem um cache para honrar um cabeçalho Cache-Control válido enviado pelo cliente. De acordo com a especificação, um cliente pode fazer solicitações com um valor de cabeçalho no-cache e forçar o servidor a gerar uma nova resposta para cada solicitação. Atualmente, não há controle do desenvolvedor sobre esse comportamento de cache ao usar o middleware, porque o middleware segue a especificação oficial de cache.

Para obter mais controle sobre o comportamento de cache, explore outros recursos de cache do ASP.NET Core. Consulte os seguintes tópicos:

Solução de problemas

O Middleware de Cache de Resposta usa IMemoryCache, que tem uma capacidade limitada. Quando a capacidade é excedida, o cache de memória é compactado.

Se o comportamento de cache não for o esperado, confirme se as respostas podem ser armazenadas em cache e capazes de serem atendidas do cache. Examine os cabeçalhos de entrada da solicitação e os cabeçalhos de saída da resposta. Habilite o registro em log para ajudar na depuração.

Ao testar e solucionar problemas de comportamento de cache, um navegador normalmente define cabeçalhos de solicitação que impedem o cache. Por exemplo, um navegador pode definir o cabeçalho Cache-Control como no-cache ou max-age=0 ao atualizar uma página. O Fiddler, o Postman e outras ferramentas podem definir explicitamente cabeçalhos de solicitação e são preferenciais para testar o cache.

Condições para cache

  • A solicitação deve resultar em uma resposta de servidor com um código de status de 200 (OK).
  • O método de solicitação deve ser GET ou HEAD.
  • O Middleware de Cache de Resposta deve ser colocado antes do middleware que exija cache. Para obter mais informações, confira Middleware do ASP.NET Core.
  • O cabeçalho Authorization não deve estar presente.
  • Os parâmetros de cabeçalho Cache-Control devem ser válidos e a resposta deve ser marcada como public e não como private.
  • O cabeçalho Pragma: no-cache não deve estar presente se o cabeçalho Cache-Control não estiver, pois o cabeçalho Cache-Control substituirá o cabeçalho Pragma quando estiver presente.
  • O cabeçalho Set-Cookie não deve estar presente.
  • Os parâmetros de cabeçalho Vary devem ser válidos e não iguais a *.
  • O valor do cabeçalho Content-Length (se definido) deve corresponder ao tamanho do corpo da resposta.
  • O IHttpSendFileFeature não é usado.
  • A resposta não deve ser obsoleta, conforme especificado pelas diretivas de cabeçalho Expires e as diretivas de cache max-age e s-maxage.
  • O buffer de resposta deve ser bem-sucedido. O tamanho da resposta deve ser menor que o SizeLimit configurado ou padrão. O tamanho do corpo da resposta deve ser menor que o MaximumBodySize configurado ou padrão.
  • A resposta deve ser armazenada em cache de acordo com RFC 9111: Cache HTTP. Por exemplo, a diretiva no-store não deve existir nos campos de cabeçalho de solicitação ou resposta. Confira RFC 9111: Cache HTTP (Seção 3: Armazenamento de Respostas em Caches para obter detalhes.

Observação

O sistema Antiforgery para gerar tokens seguros e evitar ataques de Solicitação Intersite Forjada (CSRF) define os cabeçalhos Cache-Control e Pragma para no-cache; assim as respostas não são armazenadas em cache. Para obter informações sobre como desabilitar tokens antiforgery para elementos de formulário HTML, confira Impedir ataques de Solicitação Intersite Forjada (XSRF/CSRF) no ASP.NET Core.

Recursos adicionais

Este artigo explica como configurar o Middleware de Cache de Resposta em um aplicativo ASP.NET Core. O middleware determina quando as respostas são armazenáveis em cache, armazena respostas e fornece respostas do cache. Para obter uma introdução ao cache HTTP e ao atributo [ResponseCache], confira Cache de Resposta.

Exibir ou baixar código de exemplo (como baixar)

Configuração

O Middleware de Cache de Resposta está implicitamente disponível para aplicativos ASP.NET Core por meio da estrutura compartilhada.

Em Startup.ConfigureServices, adicione o Middleware de Cache de Resposta à coleção de serviços:

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

Configure o aplicativo para usar o middleware com o método de extensão UseResponseCaching, que adiciona o middleware ao pipeline de processamento de solicitação em 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();
    });
}

Aviso

UseCors deve ser chamado antes de UseResponseCaching ao usar o middleware CORS.

O aplicativo de exemplo adiciona cabeçalhos para controlar o cache nas solicitações seguintes:

  • Cache-Control: armazena em cache respostas armazenáveis em cache por até 10 segundos.
  • Vary: configura o middleware para atender a uma resposta armazenada em cache somente se o cabeçalho Accept-Encoding das solicitações seguintes corresponder ao da solicitação original.
// 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();
});

Os cabeçalhos anteriores não são gravados na resposta e são substituídos quando um controlador, ação ou Página Razor:

  • Tiver um atributo [ResponseCache]. Isso se aplica mesmo que uma propriedade não esteja definida. Por exemplo, omitir a propriedade VaryByHeader fará com que o cabeçalho correspondente seja removido da resposta.

O Middleware de Cache de Resposta armazena em cache apenas as respostas do servidor que resultam em um código de status 200 (OK). Todas as outras respostas, incluindo páginas de erro, são ignoradas pelo middleware.

Aviso

As respostas que contêm conteúdo para clientes autenticados devem ser marcadas como não armazenáveis em cache para impedir que o middleware armazene e forneça essas respostas. Confira Condições de cache para obter detalhes sobre como o middleware determina se uma resposta é armazenável em cache.

Opções

As opções de cache de resposta são mostradas na tabela a seguir.

Opção Descrição
MaximumBodySize O maior tamanho armazenável em cache para o corpo da resposta em bytes. O valor padrão é 64 * 1024 * 1024 (64 MB).
SizeLimit O limite de tamanho para o middleware de cache de resposta em bytes. O valor padrão é 100 * 1024 * 1024 (100 MB).
UseCaseSensitivePaths Determina se as respostas são armazenadas em cache em caminhos que diferenciam maiúsculas de minúsculas. O valor padrão é false.

O exemplo a seguir configura o middleware para:

  • Respostas de cache com um tamanho de corpo menor ou igual a 1.024 bytes.
  • Armazene as respostas por caminhos que diferenciam maiúsculas de minúsculas. Por exemplo, /page1 e /Page1 são armazenados separadamente.
services.AddResponseCaching(options =>
{
    options.MaximumBodySize = 1024;
    options.UseCaseSensitivePaths = true;
});

VaryByQueryKeys

Ao usar MVC, controladores de API Web ou os modelos de página de Páginas Razor, o atributo [ResponseCache] especifica os parâmetros necessários para definir os cabeçalhos apropriados para o cache de resposta. O único parâmetro do atributo [ResponseCache] que exige estritamente o middleware é VaryByQueryKeys, que não corresponde a um cabeçalho HTTP real. Para obter mais informações, confira Cache de resposta no ASP.NET Core.

Ao não usar o atributo [ResponseCache], o cache de resposta pode ser variado com VaryByQueryKeys. Use o ResponseCachingFeature diretamente do HttpContext.Features:

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

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

O uso de um único valor igual a * em VaryByQueryKeys varia o cache de acordo com todos os parâmetros de consulta de solicitação.

Cabeçalhos HTTP usados pelo Middleware de Cache de Resposta

A tabela a seguir fornece informações sobre cabeçalhos HTTP que afetam o cache de resposta.

parâmetro Detalhes
Authorization A resposta não será armazenada em cache se o cabeçalho existir.
Cache-Control O middleware considera apenas as respostas de cache marcadas com a diretiva de cache public. Controlar o cache com os seguintes parâmetros:
  • max-age
  • max-stale†
  • min-fresh
  • must-revalidate
  • no-cache
  • no-store
  • only-if-cached
  • particulares
  • públicos
  • s-maxage
  • proxy-revalidate‡
†Se nenhum limite for especificado para max-stale, o middleware não executará nenhuma ação.
proxy-revalidate tem o mesmo efeito que must-revalidate.

Para obter mais informações, confira RFC 9111: Diretivas de Solicitação.
Pragma Um cabeçalho Pragma: no-cache na solicitação produz o mesmo efeito que Cache-Control: no-cache. Esse cabeçalho é substituído pelas diretivas relevantes no cabeçalho Cache-Control, se presente. Considerado para compatibilidade com versões anteriores com HTTP/1.0.
Set-Cookie A resposta não será armazenada em cache se o cabeçalho existir. Qualquer middleware no pipeline de processamento de solicitações que defina um ou mais cookies impede que o Middleware de Cache de Resposta armazene em cache a resposta (por exemplo, o provedor TempData baseado em cookie).
Vary O cabeçalho Vary é usado para variar a resposta armazenada em cache por outro cabeçalho. Por exemplo, armazene respostas em cache codificando incluindo o cabeçalho Vary: Accept-Encoding, que armazena em cache respostas para solicitações com cabeçalhos Accept-Encoding: gzip e Accept-Encoding: text/plain separadamente. Uma resposta com um valor de cabeçalho de * nunca é armazenada.
Expires Uma resposta considerada obsoleta por esse cabeçalho não é armazenada nem recuperada, a menos que seja substituída por outros cabeçalhos Cache-Control.
If-None-Match A resposta completa é servida a partir do cache se o valor não for * e o ETag da resposta não corresponder a nenhum dos valores fornecidos. Caso contrário, uma resposta 304 (Não Modificada) será atendida.
If-Modified-Since Se o cabeçalho If-None-Match não estiver presente, uma resposta completa será atendida do cache se a data de resposta armazenada em cache for mais recente do que o valor fornecido. Caso contrário, uma resposta 304 – Não Modificada será atendida.
Date Ao servir do cache, o cabeçalho Date será definido pelo middleware se ele não tiver sido fornecido na resposta original.
Content-Length Ao servir do cache, o cabeçalho Content-Length será definido pelo middleware se ele não tiver sido fornecido na resposta original.
Age O cabeçalho Age enviado na resposta original é ignorado. O middleware calcula um novo valor ao servir uma resposta armazenada em cache.

O armazenamento em cache respeita as diretivas do Cache-Control da solicitação

O middleware respeita as regras do RFC 9111: Cache HTTP (Seção 5.2. Cache-Control). As regras exigem um cache para honrar um cabeçalho Cache-Control válido enviado pelo cliente. De acordo com a especificação, um cliente pode fazer solicitações com um valor de cabeçalho no-cache e forçar o servidor a gerar uma nova resposta para cada solicitação. Atualmente, não há controle do desenvolvedor sobre esse comportamento de cache ao usar o middleware, porque o middleware segue a especificação oficial de cache.

Para obter mais controle sobre o comportamento de cache, explore outros recursos de cache do ASP.NET Core. Consulte os seguintes tópicos:

Solução de problemas

Se o comportamento de cache não for o esperado, confirme se as respostas podem ser armazenadas em cache e capazes de serem atendidas do cache. Examine os cabeçalhos de entrada da solicitação e os cabeçalhos de saída da resposta. Habilite o registro em log para ajudar na depuração.

Ao testar e solucionar problemas de comportamento de cache, um navegador pode definir cabeçalhos de solicitação que afetam o cache de maneiras indesejáveis. Por exemplo, um navegador pode definir o cabeçalho Cache-Control como no-cache ou max-age=0 ao atualizar uma página. As ferramentas a seguir podem definir explicitamente cabeçalhos de solicitação e são preferenciais para testar o cache:

Condições para cache

  • A solicitação deve resultar em uma resposta de servidor com um código de status de 200 (OK).
  • O método de solicitação deve ser GET ou HEAD.
  • Em Startup.Configure, o Middleware de Cache de Resposta deve ser colocado antes do middleware que exija cache. Para obter mais informações, confira Middleware do ASP.NET Core.
  • O cabeçalho Authorization não deve estar presente.
  • Os parâmetros de cabeçalho Cache-Control devem ser válidos e a resposta deve ser marcada como public e não como private.
  • O cabeçalho Pragma: no-cache não deve estar presente se o cabeçalho Cache-Control não estiver, pois o cabeçalho Cache-Control substituirá o cabeçalho Pragma quando estiver presente.
  • O cabeçalho Set-Cookie não deve estar presente.
  • Os parâmetros de cabeçalho Vary devem ser válidos e não iguais a *.
  • O valor do cabeçalho Content-Length (se definido) deve corresponder ao tamanho do corpo da resposta.
  • O IHttpSendFileFeature não é usado.
  • A resposta não deve ser obsoleta, conforme especificado pelas diretivas de cabeçalho Expires e as diretivas de cache max-age e s-maxage.
  • O buffer de resposta deve ser bem-sucedido. O tamanho da resposta deve ser menor que o SizeLimit configurado ou padrão. O tamanho do corpo da resposta deve ser menor que o MaximumBodySize configurado ou padrão.
  • A resposta deve ser armazenada em cache de acordo com RFC 9111: Cache HTTP. Por exemplo, a diretiva no-store não deve existir nos campos de cabeçalho de solicitação ou resposta. Confira RFC 9111: Cache HTTP (Seção 3: Armazenamento de Respostas em Caches para obter detalhes.

Observação

O sistema Antiforgery para gerar tokens seguros e evitar ataques de Solicitação Intersite Forjada (CSRF) define os cabeçalhos Cache-Control e Pragma para no-cache; assim as respostas não são armazenadas em cache. Para obter informações sobre como desabilitar tokens antiforgery para elementos de formulário HTML, confira Impedir ataques de Solicitação Intersite Forjada (XSRF/CSRF) no ASP.NET Core.

Recursos adicionais