Asp.net-Mvc

ASP.NET MVC 3 中的 OutputCache 行為

  • December 11, 2010

我只是在 ASP.NET MVC 3 的 RC 版本中測試輸出記憶體。

不知何故,它不尊重 VaryByParam 屬性(或者更確切地說,我不確定我是否理解發生了什麼):

public ActionResult View(UserViewCommand command) {

在這裡,UserViewCommand 有一個名為 slug 的屬性,用於從數據庫中查找使用者。

這是我的 OutputCache 聲明:

[HttpGet, OutputCache(Duration = 2000, VaryByParam = "None")]

但是,當我嘗試使用不同的“slug”值(通過操縱 URL)來點擊 Action 方法時,而不是提供錯誤的數據(我試圖通過設計強制執行),而是呼叫 action 方法。

例如(按呼叫順序)

/user/view/abc -> 使用 slug = abc 呼叫動作方法 /user/view/abc -> 未呼叫動作方法 /user/view/xyz -> 再次使用 slug = xyz 呼叫動作方法!它不應該因為 VaryByParam = none 而從記憶體中出來嗎?

另外,在這種情況下,推薦的 OutputCaching 方法是什麼?(上面的例子)

只是想添加此資訊,以便幫助人們搜尋:

在最新版本(ASP.NET MVC 3 RC 2)中,OutputCache 行為已更改為“如預期”:

http://weblogs.asp.net/scottgu/archive/2010/12/10/announcing-asp-net-mvc-3-release-candidate-2.aspx

ASP.NET MVC 團隊(和顧大師)一路走好!你們都太棒了!

VaryByParam 僅在 url 的值看起來像/user/view?slug=abc. 參數必須是 QueryString 參數,而不是像上面的範例一樣的 url 的一部分。造成這種情況的原因很可能是因為記憶體發生在任何 url 映射之前,並且該映射不包含在記憶體中。

更新

下面的程式碼將帶你去你想去的地方。它不考慮Authorized過濾器之類的東西或任何東西,但它會根據控制器/動作/ID進行記憶體,但如果您設置ignore =“slug”,它將忽略該特定屬性

public class ActionOutputCacheAttribute : ActionFilterAttribute {
   public ActionOutputCacheAttribute(int cacheDuration, string ignore) {
       this.cacheDuration = cacheDuration;
       this.ignore = ignore;
   }

   private int cacheDuration;
   private string cacheKey;
   private string ignore;

   public override void OnActionExecuting(ActionExecutingContext filterContext) {
       string url = filterContext.HttpContext.Request.Url.PathAndQuery;
       this.cacheKey = ComputeCacheKey(filterContext);

       if (filterContext.HttpContext.Cache[this.cacheKey] != null) {
           //Setting the result prevents the action itself to be executed
           filterContext.Result =
           (ActionResult)filterContext.HttpContext.Cache[this.cacheKey];
       }

       base.OnActionExecuting(filterContext);
   }

   public override void OnActionExecuted(ActionExecutedContext filterContext) {
       //Add the ActionResult to cache 
       filterContext.HttpContext.Cache.Add(this.cacheKey, filterContext.Result,null, DateTime.Now.AddSeconds(cacheDuration),
         System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);

       //Add a value in order to know the last time it was cached.
       filterContext.Controller.ViewData["CachedStamp"] = DateTime.Now;

       base.OnActionExecuted(filterContext);
   }

   private string ComputeCacheKey(ActionExecutingContext filterContext) {
       var keyBuilder = new StringBuilder();
       keyBuilder.Append(filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
       keyBuilder.Append(filterContext.ActionDescriptor.ActionName);

       foreach (var pair in filterContext.RouteData.Values) {
           if (pair.Key != ignore) 
               keyBuilder.AppendFormat("rd{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode());
       }
       return keyBuilder.ToString();
   }
}

引用自:https://stackoverflow.com/questions/4257337