Kešování hotových stránek či v případě MVC výsledků view je jedním z mnoha způsobů, jak zvýšit výkon aplikace. Samozřejmě nic není zadarmo a v případě kešování se platí spotřebovanou pamětí. Ale i u kešování mohou nastat na první pohled zanedbatelné problémy, obzvláště v případě, že kešováný obsah je nějakým způsobem závislý například na nastaveném jazyku či kultuře volajícího.
V jednom ASP.NET MVC projektu bylo použito partial view volané přes akci z několika dalších view, tedy typicky view obsahovalo toto volání:
@{ Html.RenderAction("JsStaticResources", "Service");
a následně v kontroleru pak bylo jen vrácení částečného view:
public ActionResult JsStaticResources()
{
return PartialView("_JsStaticResources");
}
{
return PartialView("_JsStaticResources");
}
V partial view se rendrovali hlavně různé hlášení a javascriptový kód. Protože je projekt vícejazyčný, hlášky se načítali z resource souborů.
Při analýze výkonu se zjistilo, že zrenderování tohoto partial view trvá poměrně dlouho - a tak byl přidán atribut OutputCache a výkonově se zdálo vše v pořádku.
[OutputCache(Duration = 600)]
public ActionResult JsStaticResources()
{
return PartialView("_JsStaticResources");
}
public ActionResult JsStaticResources()
{
return PartialView("_JsStaticResources");
}
Aplikace je používaná zejména v anglicky mluvících zemích a tedy i testování je prováděno většinou s ohledem na tuto skutečnost. A tak se přehlédlo, že čínský uživatel může najednou vidět anglická hlášení a nebo - což by byl horší případ - pokud prvním uživatelm po spuštění aplikace byl člověk, jehož rodným jazykem je čínština, tak by ostatní uživatelé viděli hlášení v čínštině.
Přitom náprava je jednoduchá, je nutné jen kešovat v závislosti na jazyce. Do souboru global.asax se doplní následující metoda (respektive se přepíše):
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (string.Compare(custom, "UICulture") == 0)
{
string cultureName = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
return cultureName;
}
return base.GetVaryByCustomString(context, custom);
}
{
if (string.Compare(custom, "UICulture") == 0)
{
string cultureName = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
return cultureName;
}
return base.GetVaryByCustomString(context, custom);
}
A deklarace atributu u příslušené akční metody, jejíž výstup chceme podmíněně kešovat se upraví takto přiřazením hodnoty k parametru VaryBuCustom:
[OutputCache(Duration = 600, VaryByCustom="UICulture")]
public ActionResult JsStaticResources()
{
return PartialView("_JsStaticResources");
}
public ActionResult JsStaticResources()
{
return PartialView("_JsStaticResources");
}
A hned vše funguje jak má:
Při používání kešování je nutné být opatrný v tom, aby počet kešovaných instancí nepřesáhl rozumný počet, respektive aby samotné kešování neztratilo význam například vzhledem k tomu, kolik paměti spotřebuje.
Žádné komentáře:
Okomentovat