69

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() :(

avs099
  • 10,000
  • 5
  • 53
  • 105
marcel_g
  • 1,732
  • 2
  • 14
  • 18
  • Try to add `location="Server"` to OutputCache attribute - you can't clear client's cache from the server – eu-ge-ne Jul 27 '09 at 19:29

5 Answers5

59

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

Babak
  • 986
  • 10
  • 16
eu-ge-ne
  • 27,373
  • 6
  • 69
  • 62
  • Of course, now I'm having trouble figuring out how to instantiate a UrlHelper inside the webservice that has the function. Arg. – marcel_g Jul 27 '09 at 15:35
  • I gave up on that attempt. I couldn't find any way to get the RequestContext to pass into the UrlHelper constructor method. So I tested it out by hard coding in "/controller/action". This shows no error, but does not clear the cache. – marcel_g Jul 27 '09 at 17:28
  • Thanks, didn't know about the HttpContextWrapper(), so that actually builds and runs. Unfortunately, it still doesn't clear the outputcache due to the varybyparam that's been set on the method attribute, so I've ended up caching the output of RenderToString using a key that includes the params to differentiate it. – marcel_g Jul 27 '09 at 18:33
  • I'll mark it as the answer anyway, because it's probably the closest possible answer anyway. – marcel_g Jul 27 '09 at 18:34
  • Question: So, if I want to use this to clear cache for the ENTIRE application, I would need to loop through all the possible conterller/action combinations and call Response.RemoveOutputCacheItem()?? If so, is there an easy way to do this? – Kevin May 20 '10 at 17:36
  • 2
    I think I answered my own question: http://stackoverflow.com/questions/11585/clearing-page-cache-in-asp-net/2876701#2876701 – Kevin May 20 '10 at 18:28
  • 9
    Just a note. In MVC3 you now need to use `Location = OutputCacheLocation.Server` and include `System.Web.UI`. `'Location="Server"` will no longer compile. – Rondel Dec 13 '11 at 15:51
  • The answers to this question suggest that Response.RemoveOutputCacheItem will not work in IIS6+ if you're using Kernel caching (which is on by default in IIS7) - to get it to work there you'll need to use their VaryByCustom approach: http://stackoverflow.com/questions/565239/any-way-to-clear-flush-remove-outputcache – Chris Moschini Apr 25 '13 at 22:58
  • With the location=client it doesn't call action after first time. But I have problem that with the location= server, it also calls the action. Is this right or it should not call the action method? – chitra Sep 22 '15 at 09:06
  • @eu-ge-ne I can't understand how to use this if i want to clear the cache of the page from which I am trying to logout and I can logout from any page of my website – Mohit Shah Mar 04 '16 at 05:35
8

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.

5

I think correct flow is:

filterContext.HttpContext.Response.Cache.SetNoStore()
Luke
  • 11,310
  • 43
  • 59
  • 67
Egor
  • 51
  • 1
  • 1
  • Thanks, this is a much better answer, because it works for all Locations. Response.Cache.SetNoStore() –  May 04 '16 at 10:33
4

Add code to AjaxHtmlOutputMethod

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

To clear output cache you can now use

HttpContext.Cache.Remove("Page");
Andrus
  • 22,189
  • 50
  • 171
  • 330
3

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

chris166
  • 4,735
  • 4
  • 22
  • 25