ASP.NET MVC 3 中的 OutputCache 行為
我只是在 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(); } }