2012-06-12 67 views
11

我已經添加輸出緩存的一對夫婦的行動,我的應用程序進行一些簡單的性能提升。但是,這些操作還需要在每次請求(它是一個視圖計數器)後通過點擊Redis數據庫來增加計數器。與輸出緩存和其他行動工作濾清器

起初,我想我可能只是調整中的操作篩選器執行,以確保觀看次數的計算順序:

public class CountersAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     //increment my counter all clever like 
     base.OnResultExecuted(filterContext); 
    } 
} 

但沒有工作;顯然OutputCacheAttribute不像一個正常的操作過濾器。然後我嘗試實現一個自定義輸出緩存:

public class OutputCacheWithCountersAttribute : OutputCacheAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     //straight to the source to get my headcount! 
     base.OnResultExecuted(filterContext); 
    } 
} 

不,也沒有工作;一旦動作被緩存,動作過濾器似乎完全被忽略。遊民。

所以,呃,有沒有辦法(沒有實現自定義輸出緩存提供者)對我來說,我保證意見正確計算是乾淨和理性呢?

回答

13

OutputCacheAttribute有限制的方式,有一個名爲DonutOutputCache的自定義屬性由Paul Hiles開發,有助於克服這些限制。

一個支持的重要特點之一是,你可以有一個動作過濾器,可調用的所有連動作標誌着次高速緩存屬性或沒有。

例如,要緩存的時間爲5秒的動作,並在同一時間,你想用一個LogThis過濾器記錄每個動作接收到一個請求時,你可以做到這一點只需通過下方,

[LogThis] 
[DonutOutputCache(Duration=5, Order=100)] 
public ActionResult Index() 

Paul

是的,與內置OutputCacheAttribute不同,即使從緩存中檢索頁面,也會執行動作過濾器 。唯一需要注意的是 需要注意過濾順序。如果您 行動過濾器實現OnResultExecuting或OnResultExecuted 那麼這些方法將在所有的情況下被執行,但對於 OnActionExecuting和OnActionExecuted,他們將僅 過濾器的DonutOutputCacheAttribute之前運行執行。這是由於 MVC阻止後續過濾器執行的方式,因爲當您設置filterContext.Result屬性時,我們需要爲 輸出緩存執行此操作。

我不認爲你可以依靠在操作篩選 是在一個動作或控制器中定義的順序。爲了確保一個過濾器運行 之前另一個,你可以利用訂單屬性,是所有ActionFilterAttribute實現本 的。沒有 順序屬性設置任何動作,默認爲-1的值,這意味着他們將 之前其有明確的訂單值濾波器執行。

因此,你的情況,你可以添加順序= 100到 DonutOutputCache屬性和所有其他過濾器 緩存過濾器前將執行。

+0

這很奇妙,除了現在我的VaryByCustom參數不工作。 GetVaryByCustomString()在全局變量中被調用,但是Donut似乎沒有遵守我所做的Response.Cache更改(即關閉認證用戶的緩存)。 – Dusda

+0

context.Response.Cache.SetCacheability(HttpCacheability.NoCache); context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(-1)); context.Response.Cache.SetNoStore(); context.Response.Cache.SetNoServerCaching(); 這些是我的Response.Cache更改;無論如何,甜甜圈似乎無視它們並緩存它。 – Dusda

+0

我將頁面視圖移動到ajax調用,而不是再混淆VaryByCustom。但是,給出的答案是解決這個問題的一個很好的方法。謝謝:D。 – Dusda

0

的原因實際上是在.NET源,並沒有與DonutOutputCache做:

public void SetCacheability(HttpCacheability cacheability) 
{ 
    if (cacheability < HttpCacheability.NoCache || HttpCacheability.ServerAndPrivate < cacheability) 
    throw new ArgumentOutOfRangeException("cacheability"); 
    if (HttpCachePolicy.s_cacheabilityValues[(int) cacheability] >= HttpCachePolicy.s_cacheabilityValues[(int) this._cacheability]) 
    return; 
    this.Dirtied(); 
    this._cacheability = cacheability; 
} 

換句話說,如果你設置NoCache的第一個(值1),它總是如果您嘗試設置較高的值,例如4(公共),則返回。

唯一的辦法是到餐桌的項目,它向你如何要求,或者發送pull請求,以紀念protected ICacheHeadersHelper CacheHeadersHelperDonutOutputCacheAttribute

1

您可以從版式視圖中的AJAX調用,甚至跟蹤訪問者如果頁面被緩存。這就是Google Analytics所做的。我建議從佈局視圖執行它,因爲它將在所有使用該佈局的視圖中執行。 還有一點評論,假設您有兩個佈局視圖:一個用於網站的公共部分,另一個用於後端(僅限員工)。您可能有興趣跟蹤用戶,而不是員工,所以這是在Layout View進行跟蹤的另一個好處。如果將來您想跟蹤員工正在做什麼,則可以爲後端佈局視圖添加一個不同的跟蹤器。 我希望它有幫助。