Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

asp.net mvc - HttpResponse.RemoveOutputCacheItem is not working

I have an ActionResult which is cached.

[OutputCache(Duration = 3600, VaryByParam = "product_Id")]
public ActionResult ProductPreview(Guid product_Id)
{
     // just for testing the cache
     System.Threading.Thread.Sleep(4000);
     return PartialView("ProductPreview", _repository.CreateProductModel(product_Id));
}

The good part is that the cache is working. After the first load, the result is shown without any 4seconds delay.

However, i need to clear the cache when some changes has been made to that product.

I tried to clear cache doing like this:

public ActionResult RemoveCache()
{
    var url = Url.Action("ProductPreview", "Common");
    // also tried with parameter
    // var url = Url.Action("ProductPreview", "Common", new { @product_Id = "productId" });
    HttpResponse.RemoveOutputCacheItem(url);

    return RedirectToAction("Index");
}

I also tried to call RemoveCache method with both ajax and full page refresh, and non of them is working.

What can i do? Where is the problem?

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The RemoveOutputCacheItem works only with route parameters, not query string. So you could modify your route definition:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{product_Id}",
    new { controller = "Home", action = "Index" }
);

Now you can use the RemoveOutputCacheItem method:

public ActionResult RemoveCache(Guid product_Id)
{
    var url = Url.Action("ProductPreview", "Common", new { product_Id = product_Id });
    // the url must look like this: /Common/ProductPreview/eeb2fe32-db58-4fc3-87c8-b47480fbe094
    // for the RemoveOutputCacheItem method to work
    HttpResponse.RemoveOutputCacheItem(url);
    return RedirectToAction("Index");
}

UPDATE:

Here's my test case:

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [OutputCache(Duration = 3600, VaryByParam = "product_id")]
    public ActionResult ProductPreview(Guid product_id)
    {
        var model = string.Format(
            "{0} - {1}", 
            product_id, 
            DateTime.Now.ToLongTimeString()
        )
        return PartialView("_Foo", model);
    }

    public ActionResult RemoveCache(Guid product_id)
    {
        var url = Url.Action(
            "ProductPreview", 
            "Home", 
            new { product_id = product_id }
        );
        HttpResponse.RemoveOutputCacheItem(url);
        return RedirectToAction("Index");
    }
}

View (~/Views/Home/Index.cshtml):

@{
    var productId = Guid.NewGuid();    
}

@Html.ActionLink("product 1", "ProductPreview", new { product_id = Guid.NewGuid() })
<br/>
@Html.ActionLink("product 2", "ProductPreview", new { product_id = productId })
<br/>
@Html.ActionLink("product 3", "ProductPreview", new { product_id = Guid.NewGuid() })
<br />

@Html.ActionLink(
    "clear cache for the second product", 
    "RemoveCache", 
    new { product_id = productId }
)

Partial view (~/Views/Home/_Foo.cshtml):

@model string
@Model

and in global.asax:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{product_id}",
        new { controller = "Home", action = "Index", product_id = UrlParameter.Optional }
    );
}

UPDATE 2:

Now that you have shown your code it seems that you are using the Html.RenderAction helper and the ProductPreview is a child action. Child actions are not stored in the same cache as normal views and the HttpResponse.RemoveOutputCacheItem helper doesn't work at all with cached child actions. If you look carefully in my previous example you will see that I used standard links for the ProductPreview action.

Currently what you are trying to achieve is not possible in ASP.NET MVC 3. If you want to use donut output caching I would recommend you the following article. Hopefully this functionality will be added in ASP.NET MVC 4.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...