ASP.NET MVC: Caching

Zarówno ASP.NET jak i ASP.NET MVC dostarczają bardzo prosty w użyciu mechanizm buforowania. Nie będę zajmował się tutaj Web Forms, a pokażę wyłącznie jak z tego korzystać w MVC.

Buforowanie oczywiście służy do szybszego wyświetlania stron. Zamiast za każdym razem, wywoływać akcję w kontrolerze, wykonuje się ją raz a potem wynik przechowuje się w pamięci.

Wyobraźmy sobie, że dana akcja wykonuje skomplikowane operacje i ponadto łączy się z różnymi bazami danych. Załóżmy, że wiele użytkowników w tym samy czasie łączy się z serwerem. Spowoduje to ogromne obciążenie. W takiej sytuacji zbuforowanie wyniku i przesyłanie go do klientów może przynieść ogromne korzyści.

Sama konfiguracja caching’u jest bardzo prosta – wystarczy użyć atrybutu OutputCache. Najpierw zdefiniujmy jednak widok:

@using System.Globalization
@model dynamic

@{
    ViewBag.Title = "title";

}

<h2>title</h2>


@DateTime.Now.ToString(CultureInfo.InvariantCulture)

Nie ma tutaj nic nadzwyczajnego. Wyświetlamy po prostu datę. Bez buforowania, za każdym odświeżeniem strony, czas byłby różny.  Następnie przejdźmy do implementacji akcji:

public class HomeController : Controller
{
   //
   // GET: /Admin/Home/
   [OutputCache(Duration = 20)]
   public ActionResult Index()
   {
       return View();
   }
}

Duration to czas ważności danego bufora. Jeśli w ciągu 20 sekund, kilkaset użytkowników wywoła /Home/Index, dostaną dokładnie tą samą, zbuforowaną stronę.

Pozostaje pytanie, gdzie kopia jest przechowywana? Dwie najważniejsze lokalizacje to serwer i klient. Jeśli wynik jest specyficzny dla danego użytkownika wtedy naturalne wydaje się, że chcemy przechowywać kopie u klienta, w przeglądarce. Załóżmy, że z jednym z elementów buforowanych to nazwa użytkownika albo inne specyficzne dla niego dane – nie chcemy w takiej sytuacji generować jednej, wspólnej dla wszystkich kopii po stronie serwera. Czasami jednak, lepiej mieć jedną kopie prezentowaną wszystkich, którą trzyma się na serwerze. Warto podkreślić, że przechowywanie po stronie klienta jest szybsze, ponieważ użytkownik nie musi wysyłać żadnego zapytania do serwera – kopia w końcu jest u niego już lokalnie na dysku. Powyższe zachowania można skonfigurować za pomocą parametru Location:

[OutputCache(Duration = 20,Location = OutputCacheLocation.Client)]
public ActionResult Index()
{
  return View();
}

Bardzo często, np. w celach testowych, chcemy zmniejszyć czas ważności kopii za pomocą pliku konfiguracyjnego. W ASP.NET możemy w łatwy sposób zrobić to za pomocą następującego kodu (Web.config):

<system.web>
    <caching>
        <outputCacheSettings>
            <outputCacheProfiles>
            <add name="profile" duration="30" enabled="true" varyByParam="pageNumber"/>
            </outputCacheProfiles>
        </outputCacheSettings>
    </caching>
</system.web>

Powyższa konfiguracja, definiuje profil buforowania o nazwie “profile”. Następnie w celu jego użycia należy  skorzystać z właściwości CacheProfile:

[OutputCache(CacheProfile = "profile")]
public ActionResult Index()
{
  return View();
}

Bardzo często, chcemy generować różne kopie w zależności od pewnych parametrów. Prawdopodobnie inną kopę chcemy posiadać dla /Home/Index/?IdEmployee=1 a inną dla /Home/Index/?IdEmployee=2. Możemy skorzystać z VaryByParam, przekazując nazwę zmiennej po której chcemy generować osobne kopie:

[OutputCache(Duration = 200,VaryByParam = "id")]
public ActionResult Index()
{
  return View();
}

Wartości możemy przekazać po przecinku, jeśli mamy kilka różnych parametrów.

Inne sposoby generowania różnych kopii to właściwości VaryByHeader oraz VaryByCustom. Pierwsza z nich analizuje nagłówek HTTP a druga z kolei, pozwala nam na zdefiniowanie własnej logiki.  VaryByCustom wywoła metodę GetVaryByCustomString, którą możemy zdefiniować w pliku Global.

Istnieje również właściwość SqlDependency, która pozwala uzależnić caching od bazy danych.

4 thoughts on “ASP.NET MVC: Caching”

Leave a Reply

Your email address will not be published.