以编程方式从OutputCacheAttribute清除缓存?

时间:2011-12-03 03:17:04

标签: asp.net-mvc-3

在我们的代码中,我们有一个用OutputCacheAttribute修饰的MVC控制器动作。在其他一些操作中是否有任何方法可以清除第一个操作的缓存?

2 个答案:

答案 0 :(得分:2)

这取决于。如果是子操作,则缓存存储在MemoryCache中,清除它的唯一方法是未记录的,并且涉及破坏整个内存缓存:

OutputCacheAttribute.ChildActionCache = new MemoryCache("NewDefault");

当然,缺点是这会删除所有缓存的子操作,而不仅仅是此子操作的缓存输出。如果这是正常操作,那么您可以使用Response.RemoveOutputCacheItem方法将其传递给缓存的操作的url。您可能还会发现following article有趣。

ASP.NET MVC 3中的缓存还有很长的路要走。希望他们在ASP.NET MVC 4中改进很多东西并简化它。

答案 1 :(得分:0)

是的,有可能 我在this book找到了答案。 请参见ASP.NET MVC中的14.3输出缓存 第372页 - 确定性地从缓存中删除项目

  

当我们使用OutputCacheAttribute,OutputCache装饰一个动作时   将其结果存储到ASP.NET缓存中并自动恢复它   什么时候它必须服务于后续的类似请求。如果我们知道哪个   页面所属的缓存键,我们可以轻松删除它。   不幸的是,这不容易实现,即使是这样,我们也是如此   我不应该知道它,因为它存在于内部逻辑中   缓存基础设施可能会在没有通知的情况下发生变化   未来版本。但是,我们可以做的是利用缓存   依赖机制实现类似的结果。这个功能是   类似于我们将在章节中讨论的变更监视器   14.4。利用缓存依赖性包括将一个缓存条目绑定到另一个缓存条目,以便在后者失效时自动删除第一个缓存条目。

一段代码

public class DependencyOutputCacheAttribute : OutputCacheAttribute
{
public string ParameterName { get; set; }
public string BasePrefix { get; set; }

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
  base.OnResultExecuting( filterContext );

  string key = string.IsNullOrEmpty( BasePrefix )
                 ? filterContext.RouteData.Values["action"] + "_" + filterContext.RouteData.Values["controller"]
                 : BasePrefix;

  key = AddToCache( filterContext, key, ParameterName);
}

private string AddToCache(ResultExecutingContext filterContext, string key, string parameter)
{
  if ( !string.IsNullOrEmpty( parameter ) && filterContext.RouteData.Values[parameter] != null) {
    key += "/" + filterContext.RouteData.Values[parameter];
    filterContext.HttpContext.Cache.AddBig( key, key );
    filterContext.HttpContext.Response.AddCacheItemDependency( key );   
  }
  return key;
}
}

删除缓存依赖关系属性

public class RemoveCachedAttribute : ActionFilterAttribute
{
public string ParameterName { get; set; }
public string BasePrefix { get; set; }
public override void OnResultExecuting( ResultExecutingContext filterContext)
{
  base.OnResultExecuting(filterContext);
  string key = string.IsNullOrEmpty(BasePrefix) ?
  filterContext.RouteData.Values["action"].ToString() + "_" +
  filterContext.RouteData.Values["controller"].ToString() : BasePrefix;
  if (!string.IsNullOrEmpty(ParameterName))
    key += filterContext.RouteData.Values[ParameterName];
  filterContext.HttpContext.Cache.Remove(key);
}
}

最后使用它

    [DependencyCache( BasePrefix = "Story", ParameterName = "id" )]
public virtual ActionResult ViewStory(int id){
//load story here
}

[HttpPost, RemoveCache( BasePrefix = "Story", ParameterName = "id" )]
public virtual ActionResult DeleteStory(int id){
//submit updated story version
}

[HttpPost, RemoveCache( BasePrefix = "Story", ParameterName = "id" )]
public virtual ActionResult EditStory(Story txt){
//submit updated story version
}

,其中

public class Story { 
  int id {get;set;} //case is important
  string storyContent{get;set;}
}