How to programmatically clear outputcache for controller action method

asp.netasp.net Mvc

asp.net Problem Overview


If the controller action has the OutputCache attribute specified on an action, is there any way to clear the output cache without having to restart IIS?

[OutputCache (Duration=3600,VaryByParam="param1;param2")]
public string AjaxHtmlOutputMethod(string param1, string param2)
{
  var someModel = SomeModel.Find( param1, param2 );

  //set up ViewData
  ...

  return RenderToString( "ViewName", someModel );
}

I'm looking at using HttpResponse.RemoveOutputCacheItem(string path) to clear it, but I'm having trouble figuring out what the path should be to map it to the action method. I'm going to try again with the aspx page that is rendered by ViewName.

Possibly I'll just manually insert the output of RenderToString into the HttpContext.Cache instead if I can't figure this one out.

Update

Please note that the OutputCache is VaryByParam, and testing out a hardcoded path "/controller/action" does not actually clear the outputcache, so it looks like it has to match "/controller/action/param1/param2".

That means I'll probably have to revert to object level caching and manually cache the output for RenderToString() :(

asp.net Solutions


Solution 1 - asp.net

Try this

var urlToRemove = Url.Action("AjaxHtmlOutputMethod", "Controller");
HttpResponse.RemoveOutputCacheItem(urlToRemove);

UPDATED:

var requestContext = new System.Web.Routing.RequestContext(
    new HttpContextWrapper(System.Web.HttpContext.Current),
    new System.Web.Routing.RouteData());

var Url = new System.Web.Mvc.UrlHelper(requestContext);

UPDATED:

Try this:

[OutputCache(Location= System.Web.UI.OutputCacheLocation.Server, Duration=3600,VaryByParam="param1;param2")]

Otherwise the cache deletion won't work because you've cached the HTML output on the user's machine

Solution 2 - asp.net

Further to the accepted answer, to support VaryByParam parameters:

  [OutputCache (Duration=3600, VaryByParam="param1;param2", Location = OutputCacheLocation.Server)]
  public string AjaxHtmlOutputMethod(string param1, string param2)
  {
       object routeValues = new { param1 = param1, param2 = param2 };

       string url = Url.Action("AjaxHtmlOutputMethod", "Controller", routeValues);

       Response.RemoveOutputCacheItem(url);
  }

However Egor's answer is much better, because it supports all OutputCacheLocation values:

  [OutputCache (Duration=3600, VaryByParam="param1;param2")]
  public string AjaxHtmlOutputMethod(string param1, string param2)
  {
       if (error)
       {
           Response.Cache.SetNoStore(); 
           Response.Cache.SetNoServerCaching();
       }
  }

When SetNoStore() and SetNoServerCaching() are called, they prevent the current Request being cached. Further requests will be cached, unless the functions are called for those requests as well.

This is ideal for handling error situations - when normally you want to cache responses, but not if they contain error messages.

Solution 3 - asp.net

I think correct flow is:

filterContext.HttpContext.Response.Cache.SetNoStore()

Solution 4 - asp.net

Add code to AjaxHtmlOutputMethod

HttpContext.Cache.Insert("Page", 1);
Response.AddCacheItemDependency("Page");

To clear output cache you can now use

HttpContext.Cache.Remove("Page");

Solution 5 - asp.net

Another option is to use VaryByCustom for the OutputCache and handle the invalidation of certain cache elements there.

Maybe it works for you, but it's not a general solution to your problem

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmarcel_gView Question on Stackoverflow
Solution 1 - asp.neteu-ge-neView Answer on Stackoverflow
Solution 2 - asp.netuser1023602View Answer on Stackoverflow
Solution 3 - asp.netEgorView Answer on Stackoverflow
Solution 4 - asp.netAndrusView Answer on Stackoverflow
Solution 5 - asp.netchris166View Answer on Stackoverflow