StackThis
StackThis

Reputation: 1252

How to bust/clear OutputCache for specific Controller/Action in ASP.NET MVC


Been struggling with this one for hours now. Here is what I am trying to solve :

I have this controller/action which uses a CacheProfile:

    [DonutOutputCache(CacheProfile = "CachedAction")]
    [ChildActionOnly]
    public ActionResult ListOrders(string id, string selectedOrders)
    {
    }

Here are my web.config settings :

    <caching>
    <outputCache enableOutputCache="true" />
    <outputCacheSettings>
        <outputCacheProfiles>
            <add name="CachedAction" duration="14100" varyByParam="id;selectedOrders" location="Any" />
        </outputCacheProfiles>
    </outputCacheSettings>

Everything works great so far and caching works as expected !!

The problem is on my page I have a little "refresh button" which the user can click to get the latest data. For this, I just do a $.ajax() call from the page after the user hits the refresh, but I call another action because if I call the original ListOrders, I will just get a cached copy of it.

    $.ajax({
        url: '/controller/myajaxrefreshaorders/1?selectedOrders=xxxx',
        type: "GET",
        async:true,
        cache: false,

And here is my problem. If you see I am just trying to bust the cache and redirect to the original action, which should simply return latest data and update the Cache. But no matter what I do, it is not working!!!

public ActionResult MyAjaxRefreshOrders(string id, string selectedOrders)
    {
        var Ocm = new OutputCacheManager();
        Ocm.RemoveItem("Controller", "ListOrders", new { id = id, selectedOrders= selectedOrders });
        Response.RemoveOutputCacheItem(Url.Action("ListOrders", "Controller", new { id = id, selectedOrders = selectedOrders }));


        return RedirectToAction("ListOrders", new { id = id, selectedOrders = selectedOrders });
    }

In fact here is my observation of what happens in reality :

  1. If I keep reloading the page, the cache works fine and it shows the timestamp of the last time the item was retrieved, which is great.
  2. If I hit that ajaxrefreshbutton, it does go to the server, goes through my cachebust code and simply returns back..i.e the call to return RedirectToAction("ListOrders") never enters that function.
  3. Finally, it appears that the ajaxcall creates another cached version of the action for me instead. So, the timestamp which shows up after the ajax call completes is a different time stamp and the time stamp which shows when I reload the page is different.

Anyone has any ideas what am I doing wrong?? I will truly appreciate your help as this is driving me nuts!

Upvotes: 0

Views: 3304

Answers (2)

Kaushik Thanki
Kaushik Thanki

Reputation: 3520

//  Get the url for the action method:
var staleItem = Url.Action("Action", "YourController", new
{
    Id = model.Id,
    area = "areaname";
});

//  Remove the item from cache
Response.RemoveOutputCacheItem(staleItem);

Also, you’ll need to remember to add the Location=OutputCacheLocation.Server parameter to the OutputCache attribute, like this:

[OutputCache(Location=System.Web.UI.OutputCacheLocation.Server, Duration = 300, VaryByParam = "Id")]

Upvotes: 1

StackThis
StackThis

Reputation: 1252

Answering my own question. Looks like this is a bug in DonutCache. What worked for me was this piece of code. (so basically, I used RemoveItems instead of RemoveItem). Craziness!!!

    var Ocm = new OutputCacheManager();
    RouteValueDictionary rv = new RouteValueDictionary();
    rv.Add("id", id);
    rv.Add("selectedorders", selectedOrders);
    Ocm.RemoveItems("controller", "listorders", rv);

A Caveat though, for some reason RedirectToAction() in MVC returns the old cached copy to the client. Not sure if it is Chrome messing with me or MVC. I suspect it is Chrome messing with that 302 redirect (even though I am using $.ajax(cache:false). The fix for me was to call methodA (BustCache) first, and then call the MVC Action after that to get the fresh data.

Upvotes: 0

Related Questions