HttpResponse.RemoveOutputCacheItem не работает

У меня есть ActionResult, который кэшируется.

[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));
}

Хорошо, что кеш работает. После первой загрузки результат отображается без задержки в 4 секунды.

Однако мне нужно очистить кеш, когда некоторые изменения были внесены в этот продукт.

Я попытался очистить кеш следующим образом:

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");
}

Я также попытался вызвать метод RemoveCache как с обновлением ajax, так и с полным обновлением страницы, и не работает.

Что я могу сделать? Где проблема?

enter image description here

Ответ 1

RemoveOutputCacheItem работает только с параметрами маршрута, а не с строкой запроса. Таким образом, вы можете изменить определение маршрута:

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

Теперь вы можете использовать метод RemoveOutputCacheItem:

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:

Здесь мой тестовый пример:

Контроллер:

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");
    }
}

Вид (~/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 }
)

Частичный вид (~/Views/Home/_Foo.cshtml):

@model string
@Model

и в 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 }
    );
}

ОБНОВЛЕНИЕ 2:

Теперь, когда вы показали свой код, кажется, что вы используете помощник Html.RenderAction, а ProductPreview - дочернее действие. Действия ребенка не сохраняются в том же кеше, что и обычные представления, а помощник HttpResponse.RemoveOutputCacheItem не работает вообще с кэшированными дочерними действиями. Если вы внимательно посмотрите в моем предыдущем примере, вы увидите, что я использовал стандартные ссылки для действия ProductPreview.

В настоящее время то, чего вы пытаетесь достичь, невозможно в ASP.NET MVC 3. Если вы хотите использовать кэширование вывода donut, я бы порекомендовал вам следующую статью. Надеемся, что эта функциональность будет добавлена ​​в ASP.NET MVC 4.