ASP.NET MVC – caching za pomocą DonutOutputCache

Kilka wpisów wcześniej pisałem o atrybucie OutputCache. Dla prostych zastosowań sprawdza się dość dobrze, ale bardzo szybko można dostrzec jego ograniczenia i błędy. Przedstawmy najpierw kilka niedogodności związanych z OutputCache.

Załóżmy, że mamy kontroler z akcją ShowTime:

[OutputCache(Duration = 5*60)]
public ActionResult ShowTime()
{
  return View();
}

Widok zawiera po prostu aktualny czas:

@DateTime.Now.ToString()

Następnie, gdzieś na stronie renderujemy powyższą akcję:

@Html.Action("ShowTime")

Na razie wszystko działa tak jak chcemy – zawartość akcji jest buforowana co 5 minut. Problem polega na tym, że implementacja w MVC nie radzi sobie dobrze z buforowaniem akcji zagnieżdżonych (child actions), takimi jak ta powyższa. Na przykład, nie wspierane są profile zdefiniowane w web.config:

<outputCacheSettings>
   <outputCacheProfiles>
       <add name="CustomProfile" duration="20" varyByParam="*" />
   </outputCacheProfiles>
</outputCacheSettings>
</caching>

Ustawienie atrybutu w następujący sposób po prostu nie zadziała:

[OutputCache(CacheProfile = "CustomProfile"]
public ActionResult ShowTime()
{
  return View();
}

Analogicznie zablokowanie buforowania w web.config działa wyłącznie dla akcji głównych a nie zagnieżdżonych:

 <outputCache enableOutputCache="false"/>

Innym wyzwaniem z jakim spotkałem się to buforowanie całej strony z wyjątkiem pewnego fragmentu np. nazwy użytkownika. Dekorując OutputCache główną akcję, nie mamy możliwości usunięcia z buforowania jakichkolwiek akcji potomnych. Na szczęście możemy ściągnąć pakiet MvcDonutOutput , który rozwiązuje powyższe problemy:

image

Sposób użycia jest analogiczny do standardowego OutputCache:

[DonutOutputCache(CacheProfile = "CustomProfile")]
public ActionResult ShowTime()
{
    return View();
}

Do dyspozycji mamy te same parametry i oczywiście teraz profile zdefiniowane w web.config działają również dla akcji potomnych.

Biblioteka rozszerza również metodę Action o argument umożliwiający nam wyłączenie specyficznej akcji z buforowania:

public static MvcHtmlString Action(this HtmlHelper html, string actionName, 
                                   string controllerName, RouteValueDictionary routeValues, 
                                   bool excludeFromParentCache)

Przykład:

@Html.Action("LoginDetails", "Account", true)

Ustawienie flagi na true spowoduje, że akcja LoginDetails nie będzie buforowana. Częstym scenariuszem jest, że chcemy buforować całą główną akcję z wyjątkiem np. jednej pokazującej dane zmieniające się bardzo często.

Możliwe jest również programowe usunięcie poszczególnych składowych z bufora:

var cacheManager = new OutputCacheManager();
 
//usuwa akcje Index z kontrolera Home
cacheManager.RemoveItem("Home", "Index");
 
// usuwa wszystkie pozycje
cacheManager.RemoveItems(); 

Myślę, że warto zastąpić OutputCache atrybutem DonutOutputCache w swoich projektach. Wcześniej czy później, każdy spotka się ze wspomnianymi ograniczeniami.

One thought on “ASP.NET MVC – caching za pomocą DonutOutputCache”

Leave a Reply

Your email address will not be published.