1

In order to implement response caching, all that is needed to be done was:

  • inject .AddResponseCaching() into the services,
  • decorate a controller action with [ResponseCache(Duration = 10)].

Now I'm trying the minimal APIs that come with .NET 6 and I haven't figured out a way to do that except add the header myself cache-control: public,max-age=10.

Is there a more elegant way to do so?

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
konkri
  • 186
  • 2
  • 12

1 Answers1

5

ResponseCacheAttribute is part of MVC and as per docs will be applied to:

  • Razor Pages: Attributes can't be applied to handler methods.
  • MVC controllers.
  • MVC action methods: Method-level attributes override the settings specified in class-level attributes.

So it seems that adding cache header yourself is an only option. If you want you can "prettify" it a little bit using custom middleware. Something along this lines:

class CacheResponseMetadata
{
// add configuration properties if needed
}

class AddCacheHeadersMiddleware
{
    private readonly RequestDelegate _next;

    public AddCacheHeadersMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        if (httpContext.GetEndpoint()?.Metadata.GetMetadata<CacheResponseMetadata>() is { } mutateResponseMetadata)
        {
            if (httpContext.Response.HasStarted)
            {
                throw new InvalidOperationException("Can't mutate response after headers have been sent to client.");
            }
            httpContext.Response.Headers.CacheControl = new[] { "public", "max-age=100" };
        }
        await _next(httpContext);
    }
}

And usage:

app.UseMiddleware<AddCacheHeadersMiddleware>(); // optionally move to extension method 
app.MapGet("/cache", () => $"Hello World, {Guid.NewGuid()}!")
    .WithMetadata(new CacheResponseMetadata()); // optionally move to extension method

.NET 7 update

For .NET 7 you can configure output caching (see the linked article for differences with response caching):

The output caching middleware can be used in all types of ASP.NET Core apps: Minimal API, Web API with controllers, MVC, and Razor Pages.

Output caching can be done per endpoint via OutputCacheAttribute or CacheOutput method call:

app.MapGet("/cached", Gravatar.WriteGravatar).CacheOutput();
app.MapGet("/attribute", [OutputCache] (context) => Gravatar.WriteGravatar(context));

Or for multiple endpoints via policy:

The following code configures caching for all of the app's endpoints, with expiration time of 10 seconds.

builder.Services.AddOutputCache(options =>
{
    options.AddBasePolicy(builder => builder.Expire(TimeSpan.FromSeconds(10)));
});
Guru Stron
  • 102,774
  • 10
  • 95
  • 132