OutputCache / ResponseCache VaryByParam

15k Views Asked by At

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?

6

There are 6 best solutions below

0
On

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" }

0
On

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.

1
On

use this in asp.net core

[ResponseCache(CacheProfileName = "TelegraphCache", VaryByQueryKeys = new[] { "id" })]
0
On

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.

0
On

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
{
   //...
}
0
On

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