Reputation: 37987
There are multiple ways to leverage ASP.Net MVC response/output caching. At the simplest you can cache a simple page that's the same for everyone:
[OutputCache(Duration=24*3600)] // cache 1 day
public ViewResult Index() ...
You can vary by specific params, you can bust the cache by a custom key. In all of those cases, the declarative OutputCacheAttribute
is used to determine whether the page should just serve from cache. If it does serve from cache, the Action doesn't fire - CPU time saved.
So, suppose the Action accepts an Id, meaning its contents vary id to id. Suppose you want to bust the cache for specific Ids when their underlying data changes. MSDN says to set VaryByCustom inside the Action instead of declaratively in OutputCacheAttribute
:
Response.Cache.SetVaryByCustom
Like:
[OutputCache(Duration=24*3600, VaryByParam="id")]
public async Task<ViewResult> Thing(string id)
{
Response.Cache.SetVaryByCustom("thing-" + id);
// Some big load of work we'd like to avoid when a ton of visitors hit
// the server goes here.
So... in every scenario until this one, that big load of work in the Action gets skipped if the page is valid in the cache. But it appears here it's not - unless SetVaryByCustom
can interrupt the Action? How does this command work exactly?
If it doesn't interrupt the Action, is there some follow-on check I can do to see if the cache picked it up, so I can return early? And what would I return, given it's normally expecting a whole page filled with data?
Upvotes: 1
Views: 427
Reputation: 37987
Based on testing, it appears to work neither of the ways I proposed.
In my Action with this strategy applied, I:
Fire a log event
Fire SetVaryByCustom(id);
Fire another log event
And here's what I saw:
BrowserA: Visit a given id
Log: Both events fire - before and after
BrowserB: Visit same id
Log: (nothing)
BrowserA: Change id so an Invalidate fires for id
BrowserB: Visit id, sees 200
Log: Both events fire - before and after
BrowserA: Visit id, sees 200
Log: (nothing)
BrowserB: Visit id, sees 304
Log: (nothing)
In other words, the entire Action doesn't fire, just like in the static/declarative approach where it's all done in OutputCacheAttribute
. What's pretty strange is each time it invalidates, the key gets an opportunity to change - you could pass a new key to SetVaryByCustom
once per invalidation, but not more.
Unless you explicitly tell ASP.Net not to, the browser is also told to cache these pages, for the length of time remaining in the 24-hr period (via max-age
). That means depending on how your visitors arrive, they may not see the page change as you intended. You can prevent this of course with Location=OutputCacheLocation.Server
in your OutputCacheAttribute
.
In any case, my core objective is in fact met - the server skips the CPU cost of the Action - just a bit more than I anticipated.
Upvotes: 1