74

After switching an ASP.NET MVC 5 application to Azure Redis (Microsoft.Web.RedisOutputCacheProvider Nuget package) I was surprised to see that OutputCacheAttribute when set to use either OutputCacheLocation.Any or OutputCacheLocation.ServerAndClient

[Route("Views/Orders")]
[OutputCache(Duration = 600, Location = OutputCacheLocation.Any)]
public ActionResult Orders()
{
}

randomly generates the following error:

When using a custom output cache provider like 'RedisOutputCache', only the following expiration policies and cache features are supported: file dependencies, absolute expirations, static validation callbacks and static substitution callbacks.

which is weird as the declaration above clearly defines just absolute expiration without any advanced stuff like varybyparam. After some searching it looks like there is no fix to this issue which is extremely frustrating. Are there any external cache providers compatible with ASP.NET caching mechanics? If not, how do you implement server side HTTP output caching in cluster scenarios in MVC/WebApi apps?

Claudio
  • 10,614
  • 4
  • 31
  • 71
UserControl
  • 14,766
  • 20
  • 100
  • 187
  • 6
    You could try placing your cluster behind a reverse proxy such as nginx. It is possible you will find it gives better performance, as you can offload the TLS and run the caching in native (as opposed to .net). – Aron May 02 '17 at 10:00
  • 1
    That's interesting, thank you! Will I have an option to programmatically invalidate nginx cache somehow? – UserControl May 02 '17 at 10:51
  • 2
    Actually you do the opposite. Look up 304 Not Modified and ETag. – Aron May 02 '17 at 11:16
  • 5
    Why do you need to specify the location if you're using a Redis Cache? That seems redundant to me. Also can you elaborate on 'randomly'? Same Action sometimes has the error sometimes does not? Some actions have it all the time some have it none of the time? – Nate Jan 10 '18 at 18:53
  • 4
    RedisOutputCacheProvider appears to be an open source project -- you can pull the project, integrate it with your project, so that when debugging you can get further context to the issue: https://github.com/Azure/aspnet-redis-providers/blob/master/src/OutputCacheProvider/RedisOutputCacheProvider.cs – ryanwebjackson Aug 04 '19 at 13:36
  • Azure Redis cache provide this option and you can use for the external caching – Rahul Shukla Apr 26 '21 at 06:49

1 Answers1

1

The issue is that if the endpoint is authenticated, then by definition the output varies by the user. So basically all external output cache providers are no longer an option.

Your options are either:

  1. Unprotect the endpoints if they could allow anonymous safely
  2. Use local caching that can vary by user
  3. Split up your endpoints so that you use child actions, and/or AJAX calls for protected data. This can allow you to make most things public, but keep the actual data un-cached and protected
  4. Cache at a different tier than output. Is your app server request/response and view rendering really your scale pain point? Or is it more likely the DB, and any service tier calculations? Caching in those layers are easy, and can vary by user easily as needed.
Tim
  • 2,878
  • 1
  • 14
  • 19