Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Av Tom Dykstra
Warning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Important
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Den här artikeln beskriver hur du konfigurerar cachelagring av utdata i en ASP.NET Core-app. En introduktion till cachelagring av utdata finns i Cachelagring av utdata.
Mellanprogrammet för cachelagring av utdata kan användas i alla typer av ASP.NET Core-appar: Minimalt API, Webb-API med styrenheter, MVC och Razor Sidor. Kodexempel tillhandahålls för minimala API:er och kontrollantbaserade API:er. De kontrollantbaserade API-exemplen visar hur du använder attribut för att konfigurera cachelagring. Dessa attribut kan också användas i MVC- och Razor Pages-appar.
Kodexemplen refererar till en Gravatar-klass som genererar en avbildning och ger ett "genererat vid" datum och tid. Klassen definieras och används endast i exempelappen. Syftet är att göra det enkelt att se när cachelagrade utdata används. Mer information finns i Ladda ned ett exempel och preprocessor-direktiv i exempelkod.
Lägg till mellanprogrammet i appen
Lägg till mellanprogrammet för cachelagring av utdata i tjänstsamlingen genom att anropa AddOutputCache.
Lägg till mellanprogrammet i pipelinen för bearbetning av begäranden genom att anropa UseOutputCache.
Till exempel:
builder.Services.AddOutputCache();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
app.UseOutputCache();
app.UseAuthorization();
Anropar AddOutputCache och UseOutputCache påbörjar inte cachelagringsbeteendet, det gör cachelagring möjligt. För att få appen att cachelagra svaren måste cachelagring konfigureras enligt de följande avsnitten.
Note
- I appar som använder CORS-mellanprogramUseOutputCachemåste anropas efter UseCors.
- I Razor Pages-appar och appar med styrfunktioner måste UseOutputCacheanropas efterUseRouting.
Konfigurera en slutpunkt eller sida
För minimala API-appar konfigurerar du en slutpunkt för cachelagring genom att anropa CacheOutputeller genom att använda [OutputCache] attributet, enligt följande exempel:
app.MapGet("/cached", Gravatar.WriteGravatar).CacheOutput();
app.MapGet("/attribute", [OutputCache] (context) => 
    Gravatar.WriteGravatar(context));
För appar med kontrollanter tillämpar du [OutputCache] attributet på åtgärdsmetoden som visas här:
[ApiController]
[Route("/[controller]")]
[OutputCache]
public class CachedController : ControllerBase
{
    public async Task GetAsync()
    {
        await Gravatar.WriteGravatar(HttpContext);
    }
}
För Razor Pages-appar använder du attributet för sidklassen Razor .
Konfigurera flera slutpunkter eller sidor
Skapa principer när du anropar AddOutputCache för att ange cachelagringskonfiguration som gäller för flera slutpunkter. En princip kan väljas för specifika slutpunkter, medan en basprincip tillhandahåller standardkonfiguration för cachelagring för en samling slutpunkter.
Följande markerade kod konfigurerar cachelagring för alla appens slutpunkter, med förfallotid på 10 sekunder. Om en förfallotid inte har angetts är den som standard en minut.
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => 
        builder.Expire(TimeSpan.FromSeconds(10)));
    options.AddPolicy("Expire20", builder => 
        builder.Expire(TimeSpan.FromSeconds(20)));
    options.AddPolicy("Expire30", builder => 
        builder.Expire(TimeSpan.FromSeconds(30)));
});
Följande markerade kod skapar två principer som var och en anger en annan förfallotid. Valda slutpunkter kan använda förfallotiden på 20 sekunder och andra kan använda 30 sekunders förfallotid.
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => 
        builder.Expire(TimeSpan.FromSeconds(10)));
    options.AddPolicy("Expire20", builder => 
        builder.Expire(TimeSpan.FromSeconds(20)));
    options.AddPolicy("Expire30", builder => 
        builder.Expire(TimeSpan.FromSeconds(30)));
});
Du kan välja en princip för en slutpunkt när du anropar CacheOutput metoden eller använder [OutputCache] attributet.
I en minimal API-app konfigurerar följande kod en slutpunkt med 20 sekunders förfallotid och en med 30 sekunders förfallotid:
app.MapGet("/20", Gravatar.WriteGravatar).CacheOutput("Expire20");
app.MapGet("/30", [OutputCache(PolicyName = "Expire30")] (context) => 
    Gravatar.WriteGravatar(context));
För appar med kontrollanter använder du [OutputCache] attributet för åtgärdsmetoden för att välja en princip:
[ApiController]
[Route("/[controller]")]
[OutputCache(PolicyName = "Expire20")]
public class Expire20Controller : ControllerBase
{
    public async Task GetAsync()
    {
        await Gravatar.WriteGravatar(HttpContext);
    }
}
För Razor Pages-appar använder du attributet för sidklassen Razor .
Standardprincip för cachelagring av utdata
Som standard följer cachelagring av utdata följande regler:
- Endast HTTP 200-svar cachelagras.
- Endast HTTP GET- eller HEAD-begäranden cachelagras.
- Svar som sätter cookies cachelagras inte.
- Svar på autentiserade begäranden cachelagras inte.
Följande kod tillämpar alla standardregler för cachelagring på alla en apps slutpunkter:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder.Cache());
});
Åsidosätt standardprincipen
Följande kod visar hur du åsidosätter standardreglerna. De markerade raderna i följande anpassade principkod aktiverar cachelagring för HTTP POST-metoder och HTTP 301-svar:
using Microsoft.AspNetCore.OutputCaching;
using Microsoft.Extensions.Primitives;
namespace OCMinimal;
public sealed class MyCustomPolicy : IOutputCachePolicy
{
    public static readonly MyCustomPolicy Instance = new();
    private MyCustomPolicy()
    {
    }
    ValueTask IOutputCachePolicy.CacheRequestAsync(
        OutputCacheContext context, 
        CancellationToken cancellationToken)
    {
        var attemptOutputCaching = AttemptOutputCaching(context);
        context.EnableOutputCaching = true;
        context.AllowCacheLookup = attemptOutputCaching;
        context.AllowCacheStorage = attemptOutputCaching;
        context.AllowLocking = true;
        // Vary by any query by default
        context.CacheVaryByRules.QueryKeys = "*";
        return ValueTask.CompletedTask;
    }
    ValueTask IOutputCachePolicy.ServeFromCacheAsync
        (OutputCacheContext context, CancellationToken cancellationToken)
    {
        return ValueTask.CompletedTask;
    }
    ValueTask IOutputCachePolicy.ServeResponseAsync
        (OutputCacheContext context, CancellationToken cancellationToken)
    {
        var response = context.HttpContext.Response;
        // Verify existence of cookie headers
        if (!StringValues.IsNullOrEmpty(response.Headers.SetCookie))
        {
            context.AllowCacheStorage = false;
            return ValueTask.CompletedTask;
        }
        // Check response code
        if (response.StatusCode != StatusCodes.Status200OK && 
            response.StatusCode != StatusCodes.Status301MovedPermanently)
        {
            context.AllowCacheStorage = false;
            return ValueTask.CompletedTask;
        }
        return ValueTask.CompletedTask;
    }
    private static bool AttemptOutputCaching(OutputCacheContext context)
    {
        // Check if the current request fulfills the requirements
        // to be cached
        var request = context.HttpContext.Request;
        // Verify the method
        if (!HttpMethods.IsGet(request.Method) && 
            !HttpMethods.IsHead(request.Method) && 
            !HttpMethods.IsPost(request.Method))
        {
            return false;
        }
        // Verify existence of authorization headers
        if (!StringValues.IsNullOrEmpty(request.Headers.Authorization) || 
            request.HttpContext.User?.Identity?.IsAuthenticated == true)
        {
            return false;
        }
        return true;
    }
}
Om du vill använda den här anpassade principen skapar du en namngiven princip:
builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("CachePost", MyCustomPolicy.Instance);
});
Och välj den namngivna principen för en slutpunkt. Följande kod väljer den anpassade principen för en slutpunkt i en minimal API-app:
app.MapPost("/cachedpost", Gravatar.WriteGravatar)
    .CacheOutput("CachePost");
Följande kod gör samma sak för en kontrollantåtgärd:
[ApiController]
[Route("/[controller]")]
[OutputCache(PolicyName = "CachePost")]
public class PostController : ControllerBase
{
    public async Task GetAsync()
    {
        await Gravatar.WriteGravatar(HttpContext);
    }
}
Alternativ åsidosättande av standardinställning
Du kan också använda Dependency Injection (DI) för att initiera en instans med följande ändringar i den anpassade policyklassen.
- En offentlig konstruktor i stället för en privat konstruktor.
- Eliminera egenskapen Instancei den anpassade principklassen.
Till exempel:
public sealed class MyCustomPolicy2 : IOutputCachePolicy
{
    public MyCustomPolicy2()
    {
    }
Resten av klassen är densamma som tidigare. Lägg till den anpassade policyn enligt exemplet nedan:
builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("CachePost", builder => 
        builder.AddPolicy<MyCustomPolicy2>(), true);
});
Föregående kod använder DI för att skapa instansen av den anpassade principklassen. Alla offentliga argument i konstruktorn löses.
När du använder en anpassad princip som en basprincip ska du inte anropa OutputCache() (utan argument) eller använda [OutputCache] attributet på någon slutpunkt som basprincipen ska gälla för. När du anropar OutputCache() eller använder attributet läggs standardprincipen till i slutpunkten.
Ange cache-nyckeln
Som standard inkluderas varje del av URL:en som nyckeln till en cachepost, det vill ex. schemat, värden, porten, sökvägen och frågesträngen. Du kanske dock uttryckligen vill styra cachenyckeln. Anta till exempel att du har en slutpunkt som returnerar ett unikt svar endast för varje unikt värde i frågesträngen culture . Variation i andra delar av URL:en, till exempel andra frågesträngar, bör inte resultera i olika cacheposter. Du kan ange sådana regler i en princip, som du ser i följande markerade kod:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
Du kan sedan välja VaryByQuery principen för en slutpunkt. I en minimal API-app väljer VaryByQuery följande kod principen för en slutpunkt som endast returnerar ett unikt svar för varje unikt värde i frågesträngen culture :
app.MapGet("/query", Gravatar.WriteGravatar).CacheOutput("Query");
Följande kod gör samma sak för en kontrollantåtgärd:
[ApiController]
[Route("/[controller]")]
[OutputCache(PolicyName = "Query")]
public class QueryController : ControllerBase
{
    public async Task GetAsync()
    {
        await Gravatar.WriteGravatar(HttpContext);
    }
}
Här är några av alternativen för att styra cachenyckeln:
- SetVaryByQuery – Ange ett eller flera frågesträngsnamn som ska läggas till i cachenyckeln. 
- SetVaryByHeader – Ange en eller flera HTTP-huvuden som ska läggas till i cachenyckeln. 
- VaryByValue– Ange ett värde som ska läggas till i cachenyckeln. I följande exempel används ett värde som anger om den aktuella servertiden i sekunder är udda eller jämn. Ett nytt svar genereras bara när antalet sekunder går från udda till jämna eller till och med udda. - builder.Services.AddOutputCache(options => { options.AddBasePolicy(builder => builder .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog")) .Tag("tag-blog")); options.AddBasePolicy(builder => builder.Tag("tag-all")); options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture")); options.AddPolicy("NoCache", builder => builder.NoCache()); options.AddPolicy("NoLock", builder => builder.SetLocking(false)); options.AddPolicy("VaryByValue", builder => builder.VaryByValue((context) => new KeyValuePair<string, string>( "time", (DateTime.Now.Second % 2) .ToString(CultureInfo.InvariantCulture)))); });
Använd OutputCacheOptions.UseCaseSensitivePaths för att ange att nyckelns sökvägsdel är skiftlägeskänslig. Standardvärdet är skiftlägesokänsligt.
Fler alternativ finns i OutputCachePolicyBuilder klassen .
Cachelagring
Cacheåtervalidering innebär att servern kan returnera en 304 Not Modified HTTP-statuskod i stället för hela svarstexten. Den här statuskoden informerar klienten om att svaret på begäran är oförändrat från det som klienten tog emot tidigare.
Följande kod illustrerar användningen av en Etag rubrik för att aktivera cacheåtervalidering. Om klienten skickar en If-None-Match rubrik med etag-värdet för ett tidigare svar och cacheposten är ny, returnerar servern 304 Inte ändrad i stället för det fullständiga svaret. Så här anger du etag-värdet i en princip i en minimal API-app:
app.MapGet("/etag", async (context) =>
{
    var etag = $"\"{Guid.NewGuid():n}\"";
    context.Response.Headers.ETag = etag;
    await Gravatar.WriteGravatar(context);
}).CacheOutput();
Så här anger du etag-värdet i ett kontrollantbaserat API:
[ApiController]
[Route("/[controller]")]
[OutputCache]
public class EtagController : ControllerBase
{
    public async Task GetAsync()
    {
        var etag = $"\"{Guid.NewGuid():n}\"";
        HttpContext.Response.Headers.ETag = etag;
        await Gravatar.WriteGravatar(HttpContext);
    }
}
Ett annat sätt att göra cacheåtervalidering är att kontrollera datumet då cacheposten skapades jämfört med det datum som begärdes av klienten. När begärandehuvudet If-Modified-Since anges returnerar cachelagring av utdata 304 om den cachelagrade posten är äldre och inte har upphört att gälla.
Cacheåtervalidering sker automatiskt som svar på dessa rubriker som skickas från klienten. Ingen särskild konfiguration krävs på servern för att aktivera det här beteendet, förutom att aktivera cachelagring av utdata.
Använda taggar för att ta bort cacheposter
Du kan använda taggar för att identifiera en grupp slutpunkter och ta bort alla cacheposter för gruppen. Följande minimala API-kod skapar till exempel ett par slutpunkter vars URL:er börjar med "blogg" och taggar dem "tag-blog":
app.MapGet("/blog", Gravatar.WriteGravatar)
    .CacheOutput(builder => builder.Tag("tag-blog"));
app.MapGet("/blog/post/{id}", Gravatar.WriteGravatar)
    .CacheOutput(builder => builder.Tag("tag-blog"));
Följande kod visar hur du tilldelar taggar till en slutpunkt i ett kontrollantbaserat API:
[ApiController]
[Route("/[controller]")]
[OutputCache(Tags = new[] { "tag-blog", "tag-all" })]
public class TagEndpointController : ControllerBase
{
    public async Task GetAsync()
    {
        await Gravatar.WriteGravatar(HttpContext);
    }
}
Ett alternativt sätt att tilldela taggar för slutpunkter med vägar som börjar med blog är att definiera en basprincip som gäller för alla slutpunkter med den vägen. Följande kod visar hur du gör det:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
Ett annat alternativ för minimala API-appar är att anropa MapGroup:
var blog = app.MapGroup("blog")
    .CacheOutput(builder => builder.Tag("tag-blog"));
blog.MapGet("/", Gravatar.WriteGravatar);
blog.MapGet("/post/{id}", Gravatar.WriteGravatar);
I föregående exempel på taggtilldelning identifieras båda slutpunkterna av taggen tag-blog . Du kan sedan ta bort cacheposterna för dessa slutpunkter med en enda instruktion som refererar till taggen:
app.MapPost("/purge/{tag}", async (IOutputCacheStore cache, string tag) =>
{
    await cache.EvictByTagAsync(tag, default);
});
Med den här koden skickas en HTTP POST-begäran till https://localhost:<port>/purge/tag-blog och raderar cacheposter för dessa slutpunkter.
Du kanske vill ha ett sätt att rensa alla cacheposter för alla slutpunkter. För att göra det skapar du en basprincip för alla slutpunkter som följande kod gör:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
Med den här basprincipen kan du använda taggen "tag-all" för att ta bort allt i cacheminnet.
Inaktivera resurslåsning
Som standard aktiveras resurslåsning för att minska risken för cachestämpling och dundrande hjord. Mer information finns i Cachelagring av utdata.
Om du vill inaktivera resurslåsning anropar du SetLocking(false) när du skapar en princip, som du ser i följande exempel:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
I följande exempel väljs principen utan låsning för en slutpunkt i en minimal API-app:
app.MapGet("/nolock", Gravatar.WriteGravatar)
    .CacheOutput("NoLock");
I ett kontrollantbaserat API använder du attributet för att välja principen:
[ApiController]
[Route("/[controller]")]
[OutputCache(PolicyName = "NoLock")]
public class NoLockController : ControllerBase
{
    public async Task GetAsync()
    {
        await Gravatar.WriteGravatar(HttpContext);
    }
}
Limits
Med följande egenskaper OutputCacheOptions kan du konfigurera gränser som gäller för alla slutpunkter:
- SizeLimit – Maximal storlek på cachelagring. När den här gränsen har nåtts cachelagras inga nya svar förrän äldre poster tas bort. Standardvärdet är 100 MB.
- MaximumBodySize – Om svarstexten överskrider den här gränsen cachelagras den inte. Standardvärdet är 64 MB.
- DefaultExpirationTimeSpan – Utgångstidens varaktighet som gäller när ingen policy anges. Standardvärdet är 60 sekunder.
Cachelagring
IOutputCacheStore används för lagring. Som standard används den med MemoryCache. Cachelagrade svar lagras i processen, så varje server har en separat cache som går förlorad när serverprocessen startas om.
Redis cache
Ett alternativ är att använda Redis-cache . Redis-cachen säkerställer konsekvens mellan servernoder genom en delad cache som överlever enskilda serverprocesser. Så här använder du Redis för cachelagring av utdata:
- Installera NuGet-paketet Microsoft.AspNetCore.OutputCaching.StackExchangeRedis . 
- Anropa - builder.Services.AddStackExchangeRedisOutputCache(inte- AddStackExchangeRedisCache) och ange en anslutningssträng som pekar på en Redis-server.- Till exempel: - builder.Services.AddStackExchangeRedisOutputCache(options => { options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr"); options.InstanceName = "SampleInstance"; }); builder.Services.AddOutputCache(options => { options.AddBasePolicy(builder => builder.Expire(TimeSpan.FromSeconds(10))); });- 
              options.Configuration– En anslutningssträng till en lokal Redis-server eller till ett värdbaserat erbjudande, till exempel Azure Cache for Redis. Till exempel<instance_name>.redis.cache.windows.net:6380,password=,pw,ssl=True,abortConnect=Falseför Azure Cache for Redis.
- 
              options.InstanceName– Valfritt, anger en logisk partition för cacheminnet.
 - Konfigurationsalternativen är identiska med redis-baserade alternativ för distribuerad cachelagring. 
- 
              
              IDistributedCache rekommenderas inte
Vi rekommenderar IDistributedCache inte för användning med cachelagring av utdata. 
              IDistributedCache har inte atomiska funktioner som krävs för taggning. Vi rekommenderar att du använder det inbyggda stödet för Redis eller skapar anpassade IOutputCacheStore implementeringar med hjälp av direkta beroenden på den underliggande lagringsmekanismen.
Se även
Den här artikeln beskriver hur du konfigurerar cachelagring av utdata i en ASP.NET Core-app. En introduktion till cachelagring av utdata finns i Cachelagring av utdata.
Mellanprogrammet för cachelagring av utdata kan användas i alla typer av ASP.NET Core-appar: Minimalt API, Webb-API med styrenheter, MVC och Razor Sidor. Exempelappen är ett minimalt API, men varje cachelagringsfunktion som den illustrerar stöds också i de andra apptyperna.
Lägg till mellanprogrammet i appen
Lägg till mellanprogrammet för cachelagring av utdata i tjänstsamlingen genom att anropa AddOutputCache.
Lägg till mellanprogrammet i pipelinen för bearbetning av begäranden genom att anropa UseOutputCache.
Note
- I appar som använder CORS-mellanprogramUseOutputCachemåste anropas efter UseCors.
- I Razor Pages-appar och appar med styrfunktioner måste UseOutputCacheanropas efterUseRouting.
- Anropar AddOutputCacheochUseOutputCachepåbörjar inte cachelagringsbeteendet, det gör cachelagring möjligt. Svarsdata för cachelagring måste konfigureras enligt följande avsnitt.
Konfigurera en slutpunkt eller sida
För minimala API-appar konfigurerar du en slutpunkt för cachelagring genom att anropa CacheOutputeller genom att använda [OutputCache] attributet, enligt följande exempel:
app.MapGet("/cached", Gravatar.WriteGravatar).CacheOutput();
app.MapGet("/attribute", [OutputCache] (context) => 
    Gravatar.WriteGravatar(context));
För appar med kontrollanter använder du attributet [OutputCache] för åtgärdsmetoden. För Razor Pages-appar använder du attributet för sidklassen Razor .
Konfigurera flera slutpunkter eller sidor
Skapa principer när du anropar AddOutputCache för att ange cachelagringskonfiguration som gäller för flera slutpunkter. En princip kan väljas för specifika slutpunkter, medan en basprincip tillhandahåller standardkonfiguration för cachelagring för en samling slutpunkter.
Följande markerade kod konfigurerar cachelagring för alla appens slutpunkter, med förfallotid på 10 sekunder. Om en förfallotid inte har angetts är den som standard en minut.
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => 
        builder.Expire(TimeSpan.FromSeconds(10)));
    options.AddPolicy("Expire20", builder => 
        builder.Expire(TimeSpan.FromSeconds(20)));
    options.AddPolicy("Expire30", builder => 
        builder.Expire(TimeSpan.FromSeconds(30)));
});
Följande markerade kod skapar två principer som var och en anger en annan förfallotid. Valda slutpunkter kan använda 20 sekunders förfallotid och andra kan använda 30 sekunders förfallotid.
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => 
        builder.Expire(TimeSpan.FromSeconds(10)));
    options.AddPolicy("Expire20", builder => 
        builder.Expire(TimeSpan.FromSeconds(20)));
    options.AddPolicy("Expire30", builder => 
        builder.Expire(TimeSpan.FromSeconds(30)));
});
Du kan välja en princip för en slutpunkt när du CacheOutput anropar metoden eller använder attributet [OutputCache] :
app.MapGet("/20", Gravatar.WriteGravatar).CacheOutput("Expire20");
app.MapGet("/30", [OutputCache(PolicyName = "Expire30")] (context) => 
    Gravatar.WriteGravatar(context));
För appar med kontrollanter använder du attributet [OutputCache] för åtgärdsmetoden. För Razor Pages-appar använder du attributet för sidklassen Razor .
Standardprincip för cachelagring av utdata
Som standard följer cachelagring av utdata följande regler:
- Endast HTTP 200-svar cachelagras.
- Endast HTTP GET- eller HEAD-begäranden cachelagras.
- Svar som sätter cookies cachelagras inte.
- Svar på autentiserade begäranden cachelagras inte.
Följande kod tillämpar alla standardregler för cachelagring på alla en apps slutpunkter:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder.Cache());
});
Åsidosätt standardprincipen
Följande kod visar hur du åsidosätter standardreglerna. De markerade raderna i följande anpassade principkod aktiverar cachelagring för HTTP POST-metoder och HTTP 301-svar:
using Microsoft.AspNetCore.OutputCaching;
using Microsoft.Extensions.Primitives;
namespace OCMinimal;
public sealed class MyCustomPolicy : IOutputCachePolicy
{
    public static readonly MyCustomPolicy Instance = new();
    private MyCustomPolicy()
    {
    }
    ValueTask IOutputCachePolicy.CacheRequestAsync(
        OutputCacheContext context, 
        CancellationToken cancellationToken)
    {
        var attemptOutputCaching = AttemptOutputCaching(context);
        context.EnableOutputCaching = true;
        context.AllowCacheLookup = attemptOutputCaching;
        context.AllowCacheStorage = attemptOutputCaching;
        context.AllowLocking = true;
        // Vary by any query by default
        context.CacheVaryByRules.QueryKeys = "*";
        return ValueTask.CompletedTask;
    }
    ValueTask IOutputCachePolicy.ServeFromCacheAsync
        (OutputCacheContext context, CancellationToken cancellationToken)
    {
        return ValueTask.CompletedTask;
    }
    ValueTask IOutputCachePolicy.ServeResponseAsync
        (OutputCacheContext context, CancellationToken cancellationToken)
    {
        var response = context.HttpContext.Response;
        // Verify existence of cookie headers
        if (!StringValues.IsNullOrEmpty(response.Headers.SetCookie))
        {
            context.AllowCacheStorage = false;
            return ValueTask.CompletedTask;
        }
        // Check response code
        if (response.StatusCode != StatusCodes.Status200OK && 
            response.StatusCode != StatusCodes.Status301MovedPermanently)
        {
            context.AllowCacheStorage = false;
            return ValueTask.CompletedTask;
        }
        return ValueTask.CompletedTask;
    }
    private static bool AttemptOutputCaching(OutputCacheContext context)
    {
        // Check if the current request fulfills the requirements
        // to be cached
        var request = context.HttpContext.Request;
        // Verify the method
        if (!HttpMethods.IsGet(request.Method) && 
            !HttpMethods.IsHead(request.Method) && 
            !HttpMethods.IsPost(request.Method))
        {
            return false;
        }
        // Verify existence of authorization headers
        if (!StringValues.IsNullOrEmpty(request.Headers.Authorization) || 
            request.HttpContext.User?.Identity?.IsAuthenticated == true)
        {
            return false;
        }
        return true;
    }
}
Om du vill använda den här anpassade principen skapar du en namngiven princip:
builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("CachePost", MyCustomPolicy.Instance);
});
Och välj den namngivna principen för en slutpunkt:
app.MapPost("/cachedpost", Gravatar.WriteGravatar)
    .CacheOutput("CachePost");
Alternativ åsidosättande av standardinställning
Du kan också använda Dependency Injection (DI) för att initiera en instans med följande ändringar i den anpassade policyklassen.
- En offentlig konstruktor i stället för en privat konstruktor.
- Eliminera egenskapen Instancei den anpassade principklassen.
Till exempel:
public sealed class MyCustomPolicy2 : IOutputCachePolicy
{
    public MyCustomPolicy2()
    {
    }
Resten av klassen är densamma som tidigare. Lägg till den anpassade policyn enligt exemplet nedan:
builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("CachePost", builder => 
        builder.AddPolicy<MyCustomPolicy2>(), true);
});
Föregående kod använder DI för att skapa instansen av den anpassade principklassen. Alla offentliga argument i konstruktorn löses.
När du använder en anpassad princip som en basprincip ska du inte anropa OutputCache() (utan argument) på någon slutpunkt som basprincipen ska gälla för. Att anropa OutputCache() lägger till standardprincipen till slutpunkten.
Ange cache-nyckeln
Som standard inkluderas varje del av URL:en som nyckeln till en cachepost, det vill ex. schemat, värden, porten, sökvägen och frågesträngen. Du kanske dock uttryckligen vill styra cachenyckeln. Anta till exempel att du har en slutpunkt som returnerar ett unikt svar endast för varje unikt värde i frågesträngen culture . Variation i andra delar av URL:en, till exempel andra frågesträngar, bör inte resultera i olika cacheposter. Du kan ange sådana regler i en princip, som du ser i följande markerade kod:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
Du kan sedan välja VaryByQuery principen för en slutpunkt:
app.MapGet("/query", Gravatar.WriteGravatar).CacheOutput("Query");
Här är några av alternativen för att styra cachenyckeln:
- SetVaryByQuery – Ange ett eller flera frågesträngsnamn som ska läggas till i cachenyckeln. 
- SetVaryByHeader – Ange en eller flera HTTP-huvuden som ska läggas till i cachenyckeln. 
- VaryByValue– Ange ett värde som ska läggas till i cachenyckeln. I följande exempel används ett värde som anger om den aktuella servertiden i sekunder är udda eller jämn. Ett nytt svar genereras bara när antalet sekunder går från udda till jämna eller till och med udda. - app.MapGet("/varybyvalue", Gravatar.WriteGravatar) .CacheOutput(c => c.VaryByValue((context) => new KeyValuePair<string, string>( "time", (DateTime.Now.Second % 2) .ToString(CultureInfo.InvariantCulture))));
Använd OutputCacheOptions.UseCaseSensitivePaths för att ange att nyckelns sökvägsdel är skiftlägeskänslig. Standardvärdet är skiftlägesokänsligt.
Fler alternativ finns i OutputCachePolicyBuilder klassen .
Cachelagring
Cacheåtervalidering innebär att servern kan returnera en 304 Not Modified HTTP-statuskod i stället för hela svarstexten. Den här statuskoden informerar klienten om att svaret på begäran är oförändrat från det som klienten tog emot tidigare.
Följande kod illustrerar användningen av en Etag rubrik för att aktivera cacheåtervalidering. Om klienten skickar en If-None-Match rubrik med etag-värdet för ett tidigare svar och cacheposten är ny, returnerar servern 304 Inte ändrad i stället för det fullständiga svaret:
app.MapGet("/etag", async (context) =>
{
    var etag = $"\"{Guid.NewGuid():n}\"";
    context.Response.Headers.ETag = etag;
    await Gravatar.WriteGravatar(context);
}).CacheOutput();
Ett annat sätt att göra cacheåtervalidering är att kontrollera datumet då cacheposten skapades jämfört med det datum som begärdes av klienten. När begärandehuvudet If-Modified-Since anges returnerar cachelagring av utdata 304 om den cachelagrade posten är äldre och inte har upphört att gälla.
Cacheåtervalidering sker automatiskt som svar på dessa rubriker som skickas från klienten. Ingen särskild konfiguration krävs på servern för att aktivera det här beteendet, förutom att aktivera cachelagring av utdata.
Använda taggar för att ta bort cacheposter
Du kan använda taggar för att identifiera en grupp slutpunkter och ta bort alla cacheposter för gruppen. Följande kod skapar till exempel ett par slutpunkter vars URL:er börjar med "blogg" och taggar dem "tag-blog":
app.MapGet("/blog", Gravatar.WriteGravatar)
    .CacheOutput(builder => builder.Tag("tag-blog"));
app.MapGet("/blog/post/{id}", Gravatar.WriteGravatar)
    .CacheOutput(builder => builder.Tag("tag-blog"));
Ett annat sätt att tilldela taggar för samma par slutpunkter är att definiera en basprincip som gäller för slutpunkter som börjar med blog:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
Ett annat alternativ är att anropa MapGroup:
var blog = app.MapGroup("blog")
    .CacheOutput(builder => builder.Tag("tag-blog"));
blog.MapGet("/", Gravatar.WriteGravatar);
blog.MapGet("/post/{id}", Gravatar.WriteGravatar);
I föregående exempel på taggtilldelning identifieras båda slutpunkterna av taggen tag-blog . Du kan sedan ta bort cacheposterna för dessa slutpunkter med en enda instruktion som refererar till taggen:
app.MapPost("/purge/{tag}", async (IOutputCacheStore cache, string tag) =>
{
    await cache.EvictByTagAsync(tag, default);
});
Med den här koden tar en HTTP POST-begäran som skickas till https://localhost:<port>/purge/tag-blog bort cacheposter för dessa slutpunkter.
Du kanske vill ha ett sätt att rensa alla cacheposter för alla slutpunkter. För att göra det skapar du en basprincip för alla slutpunkter som följande kod gör:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
Med den här basprincipen kan du använda taggen "tag-all" för att ta bort allt i cacheminnet.
Inaktivera resurslåsning
Som standard aktiveras resurslåsning för att minska risken för cachestämpling och dundrande hjord. Mer information finns i Cachelagring av utdata.
Om du vill inaktivera resurslåsning anropar du SetLocking(false) när du skapar en princip, som du ser i följande exempel:
builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder
        .With(c => c.HttpContext.Request.Path.StartsWithSegments("/blog"))
        .Tag("tag-blog"));
    options.AddBasePolicy(builder => builder.Tag("tag-all"));
    options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
    options.AddPolicy("NoCache", builder => builder.NoCache());
    options.AddPolicy("NoLock", builder => builder.SetLocking(false));
});
I följande exempel väljs principen för ingen låsning för en slutpunkt:
app.MapGet("/nolock", Gravatar.WriteGravatar)
    .CacheOutput("NoLock");
Limits
Med följande egenskaper OutputCacheOptions kan du konfigurera gränser som gäller för alla slutpunkter:
- SizeLimit – Maximal storlek på cachelagring. När den här gränsen har nåtts cachelagras inga nya svar förrän äldre poster tas bort. Standardvärdet är 100 MB.
- MaximumBodySize – Om svarstexten överskrider den här gränsen cachelagras den inte. Standardvärdet är 64 MB.
- DefaultExpirationTimeSpan – Utgångstidens varaktighet som gäller när ingen policy anges. Standardvärdet är 60 sekunder.
Cachelagring
              IOutputCacheStore används för lagring. Som standard används den med MemoryCache. Vi rekommenderar IDistributedCache inte för användning med cachelagring av utdata. 
              IDistributedCache har inte atomiska funktioner som krävs för taggning. Vi rekommenderar att du skapar anpassade IOutputCacheStore implementeringar med hjälp av direkta beroenden för den underliggande lagringsmekanismen, till exempel Redis. Eller använd det inbyggda stödet för Redis Cache i .NET 8..
Se även
ASP.NET Core