OutputCache / ResponseCache VaryByParam
Asked Answered
G

7

17

ResponseCache is somewhat a replacement for OutputCache; however, I would like to do server side caching as well as per parameter input.

According to some answers here and here, I should be using IMemoryCache or IDistributedCache to do this. I'm particularly interested in caching on controllers where the parameter is different, previously done in asp.net 4 with OutputCache and VaryByParam like so:

[OutputCache(CacheProfile = "Medium", VaryByParam = "id", Location = OutputCacheLocation.Server)]
public ActionResult Index(long id) 
{ 
    ///...
}

How would I go about replicating this in asp.net core?

Gumption answered 27/1, 2016 at 3:0 Comment(2)
Did you solved it?Brannen
Just a heads up: while you are referring to .Net Framework OutputCacheAttribute there is also a new one in Asp.net Core 7. See my answer.Mascara
A
11

If you want to change the cache by all request query parameters in all requests in the controller:

[ResponseCache(Duration = 20, VaryByQueryKeys = new[] { "*" })]
public class ActiveSectionController : ControllerBase
{
   //...
}
Apo answered 22/11, 2019 at 9:12 Comment(0)
M
10

First be sure you are using ASP.NET Core 1.1 or higher.

Then use a code similar to this on your controller method:

[ResponseCache(Duration = 300, VaryByQueryKeys = new string[] { "date_ref" } )]
public IActionResult Quality(DateTime date_ref)

Source: https://learn.microsoft.com/en-us/aspnet/core/performance/caching/middleware

Marley answered 13/6, 2017 at 16:42 Comment(0)
M
5

Asp.Net Core 7 added Output Caching middleware. This does exactly what you want, i.e. server caching. This is not to be confused with the old .Net Framework OutputCacheAttribute you are referring to.

The main difference between OutputCache and ResponseCache:

  • OutputCache is just for server caching (it doesn't even have a Location property)
  • ResponseCache is mainly for browser caching and uses the HTTP cache headers

You can probably use them both for the same endpoint.

Mascara answered 23/11, 2022 at 18:10 Comment(0)
U
3

use this in asp.net core

[ResponseCache(CacheProfileName = "TelegraphCache", VaryByQueryKeys = new[] { "id" })]
Ultimogeniture answered 4/12, 2019 at 8:45 Comment(1)
But this is not caching when deployed on server. Request 1 -> response time 5 seconds Request 2 -> Response time is also 5 seconds but it returns Age and cache controls max age Any thing missing while deploying on server. Pls helpAlchemy
A
1

For someone whose looking for the answer... after all there is IMemoryCache but not as pretty as old days ActionFilterAttribute But with more flexibility.
Long story short (for .Net core 2.1 mostly By Microsoft docs + my understands):
1- Add services.AddMemoryCache(); service into ConfigureServices in Startup.cs file.
2- inject the service into your controller:

public class HomeController : Controller
{
  private IMemoryCache _cache;

  public HomeController(IMemoryCache memoryCache)
  {
      _cache = memoryCache;
  }

3- arbitrarily (in order to prevent typo) declare a static class which holds bunch of key's names:

public static class CacheKeys
{
  public static string SomeKey { get { return "someKey"; } }
  public static string AnotherKey { get { return "anotherKey"; } }
  ... list could be goes on based on your needs ...

I prefer to declare an enum instead:
public enum CacheKeys { someKey, anotherKey, ...}
3- Play with it in actionMethods like this:
For get cached value: _cache.TryGetValue(CacheKeys.SomeKey, out someValue)
Or Reset value if TryGetValue if fail:

_cache.Set(CacheKeys.SomeKey, 
           newCachableValue, 
           new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(60)));  

END.

Amadoamador answered 28/8, 2018 at 15:8 Comment(0)
C
1

I encountered the same issue, none of the followings produce the expected cached-by-unique-parameters-values. Always returns the initial result:

VaryByQueryKeys = new[] { "*" }

VaryByQueryKeys = new[] { "searchparam" }

given public async Task<IActionResult> Search([FromQuery] string searchparam)

Solution is prefix it with a $, that is VaryByQueryKeys = new[] { "$searchparam" }

Cerda answered 9/11, 2022 at 19:22 Comment(0)
R
0

The Microsoft documentation for this for .NET7 and .NET8 aren't that clear in my opinion, but I figured it out for Minimal APIs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOutputCache(); // add this
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseOutputCache(); // add this

app.MapGet("/products/{id}", async (string id) =>
{
    return Results.Ok("someresult");
}).CacheOutput(c => c.VaryByValue((context) =>
    new KeyValuePair<string, string>(
        "id", 
        context.Request.RouteValues["id"].ToString())));

app.Run();
Rawlins answered 9/5 at 16:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.