我做了研究,但没有找到任何答案。

我在母版页中使用Html.RenderAction(以显示具有特定于用户权限的链接的页眉)。动作用OutputCache装饰,返回部分控制并按预期进行缓存。

事件发生时(假设权限已更改),我想以编程方式使缓存的部分控件无效。

我正在尝试使用RemoveOutputCacheItem方法。它以路径作为参数。我正在尝试设置Html.RenderAction中使用的操作的路径。那不会使动作无效。

如何以编程方式使操作无效?

谢谢

最佳答案

子操作的缓存存储在OutputCacheAttribute.ChildActionCache属性中。问题在于,为子操作生成ID并将其存储在此对象中的API不是公开的(WHY Microsoft ??)。因此,如果您尝试遍历此集合中的对象,您会发现它还将包含子操作的缓存值,但是除非您对用于生成看起来像密钥的算法进行反向工程,否则您将无法识别它。像这样(用Reflector看到):

internal string GetChildActionUniqueId(ActionExecutingContext filterContext)
{
    StringBuilder builder = new StringBuilder();
    builder.Append("_MvcChildActionCache_");
    builder.Append(filterContext.ActionDescriptor.UniqueId);
    builder.Append(DescriptorUtil.CreateUniqueId(new object[] { this.VaryByCustom }));
    if (!string.IsNullOrEmpty(this.VaryByCustom))
    {
        string varyByCustomString = filterContext.HttpContext.ApplicationInstance.GetVaryByCustomString(HttpContext.Current, this.VaryByCustom);
        builder.Append(varyByCustomString);
    }
    builder.Append(GetUniqueIdFromActionParameters(filterContext, SplitVaryByParam(this.VaryByParam)));
    using (SHA256 sha = SHA256.Create())
    {
        return Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString())));
    }
}


因此,您可以执行以下疯狂操作:

public ActionResult Invalidate()
{
    OutputCacheAttribute.ChildActionCache = new MemoryCache("NewDefault");
    return View();
}


这显然会使所有缓存的子操作无效,这些操作可能不是您要找的,但恐怕是唯一的方法,除了对密钥生成进行逆向工程:-)。

@Microsoft,请,我求您使用ASP.NET MVC 4.0:


除了甜甜圈孔缓存之外,还引入了进行甜甜圈缓存的可能性
引入了使缓存的控制器操作的结果容易过期的可能性(MVCish比Response.RemoveOutputCacheItem更多)
引入了使过期的子操作的结果轻松过期的可能性
如果您这样做1.那么显然会引入使缓存的甜甜圈部分过期的可能性。

09-28 15:09