2

Does anyone know if it's possible to cancel output caching in code? What I mean is if I place output caching on a child action as follows can I then based on a condition cancel that caching from inside the child action?

[ChildActionOnly]
[OutputCache(Duration = 36000, VaryByParam="tagslug")]
public virtual ActionResult MostViewed(string tagslug, int count)
{
    // Make an API call here. If not data returned do not cache the ChildAction as specified above
}
4

1 回答 1

1

Skimming the framework source it looks like the only logic is don't-cache-on-exception:

// Only cache output if this wasn't an error
if (!wasException) {
    ChildActionCacheInternal.Add(uniqueId, capturedText,
                                 DateTimeOffset.UtcNow.AddSeconds(Duration));
}

I can't see a brilliant way to solve this: I think you'll have to make your own custom OutputCachingAttribute based on the original source from the ASP.NET MVC source from CodePlex, and then either add an extra check to that line for the output returned e.g.

if (!(wasException || capturedText.Contains("results:0"))) {

or similar, or find a way to pass that code a flag to this from your controller. The existing code uses an object to store a value on the session; you could copy this, e.g.

  1. define a new static object key the same as _childActionFilterFinishCallbackKey e.g. _noCacheResultKey
  2. add a public static method to the attribute that you can call e.g.

    public static void FlagNoCache(HttpContext httpContext) {
        httpContext.Items[_noCacheResultKey] = true;
    }
    
  3. extend ClearChildActionFilterFinishCallback to remove this from .Items[] as well as the callback
  4. extend the above test to check this too e.g.

    if (!(wasException
          || filterContext.HttpContext.Items.ContainsKey(_noCacheResultKey))) {
    
  5. from your controller call MyOutputCacheAttribute.FlagNoCache(Context); as necessary.

It may also be possible to throw an exception from your code and then catch it in a different IExceptionFilter so that it doesn't get passed up beyond the OutputCacheAttribute but I don't know how sorry.

于 2012-11-29T14:36:29.720 回答