V tomto článku si ukážeme, jak můžeme sami cachovat libovolné objekty v aplikaci ASP.NET. Příkladem může být generování obrázku, v takové aplikaci nám standardní direktiva OutputCache nepomůže, a tak se o cachování musíme postarat sami.

Nejprve je dobré si říct, proč nemůžeme použít OutputCache direktivu, popisovanou v předchozím článku. Pokud se podíváte na zmiňovaný článek o generování obrázku, uvidíte, že stránka negeneruje žádný textový výstup (není odesílán HTML kód), výstupem je binární tok dat dynamicky generovaného obrázku. Pro toto použití ASP.NET aplikace není direktiva stránky OutputCache připravena (.NET Framework verze 1.1), a tak výsledkem jejího použití by bylo pouze odeslání nesprávných hlaviček. Obrázek pak nebude cachován, generovat se bude vždy, a navíc se v některých prohlížečích ani nemusí zobrazit jako obrázek (viděli byste jen změť znaků, protože se prohlížeč snaží binární obsah zobrazit jako HTML dokument).

Snadnou pomocí je obsloužit si cachování využitím metod třídy System.Web.Caching.Cache. V tomto článku se seznámíme se základním postupem – vložit objekt do cache, otestovat, jestli je v cache a pokud ano, použít jej z cache. V jednoduchosti si můžeme práci s cache představit jako práci s cookies. Stejně jako cookie je možné objekt uložit na určenou dobu (možno nastavit expiraci) a naopak objekt z cache získat, pokud tam je a nevypršela jeho expirace. Také je možné zrušit jeho platnost nebo nastavit závislost platnosti na jiném objektu.

Objekt do cache vložíme metodou insert() – například Cache.Insert(jméno_položky,datový_typ). Objekt vyjmeme z cache jako položku danou indexem názvu požadované položky – například (datový_typ) Cache[jméno_položky], přičemž uvádíme, jakého typu mají být vytahovaná data (oproti ostatním jazykům je v C# položka – item – indexer třídy Cache).

Metod, vlastností a členů má třída Cache mnohem víc (pro zmiňované nastavování expirace, závislosti a jiné), nám však pro jednoduché vložení do cache a pozdější vyjmutí postačí ony dvě zmíněné- na ukázce generování obrázkového nadpisu si ukážeme, jak vygenerovaný obrázek vložit do cache, aby pro další požadavky už neprobíhalo znovu jeho generování, ale data obrázku byla odeslána rovnou z cache. Pro jednoduchost z předchozího příkladu vynecháme přebírání velikosti, typu písma a barvy z QueryStringu, budou v aplikaci nastavené napevno.

<%@Page Language=“C#“ EnableViewState=“False“ EnableSessionState=“False“ Trace=“False“ Debug=“False“ %>
<%@Import Namespace=“System.IO“ %>
<%@Import Namespace=“System.Drawing“ %>
<%@Import Namespace=“System.Drawing.Imaging“ %>
<script language=“C#“ runat=“server“>
void Page_Load (Object sender, EventArgs e)
{
  string HeadingText = Request.QueryString[„text“].ToString(); // převzít text nadpisu
  MemoryStream PngStream = new MemoryStream(); // deklarace memorystreamu pro data obrázku
  if ((MemoryStream) Cache[HeadingText]!=null) // ověřit, zda je memorystream obrázku v cache
  { // naplnit náš memorystream z cache
    PngStream=(MemoryStream) Cache[HeadingText];
  }
  else
  { // není v cache, nutno vygenerovat
    int nWidth = 400;
    int nHeight = 23;
    Bitmap newBitmap = new Bitmap(nWidth,nHeight,PixelFormat.Format24bppRgb);
    Graphics MyGraphicObj = Graphics.FromImage(newBitmap);
    MyGraphicObj.FillRectangle(new SolidBrush(Color.White), new Rectangle(0,0,nWidth,nHeight));
    SolidBrush gridBrush = new SolidBrush(Color.FromArgb(0x00, 0xFF, 0x66));
    Font gridFont = new Font(„Tele-Antiqua“, 22, FontStyle.Regular, GraphicsUnit.Pixel);
    MyGraphicObj.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
    MyGraphicObj.DrawString(HeadingText, gridFont, gridBrush, -4, -1);
    gridBrush.Dispose();
    gridFont.Dispose();
    MyGraphicObj.Dispose();
    newBitmap.Save(PngStream,ImageFormat.Png); // uložit bitmapu obrázku do memorystreamu
    newBitmap.Dispose();
    Cache.Insert(HeadingText,PngStream); // memorystream s daty obrázku vložit do cache
  }
  Response.ClearContent();
  Response.ContentType = „image/png“;
  Response.BinaryWrite(PngStream.GetBuffer()); // odeslat obsah memorystreamu do browseru
  PngStream.Close();
  Response.End();
}
</script>

Do skriptu jsem uvedl jen nezbytné komentáře týkající se práce s cache, pro podrobnější vysvětlení odkazuji na již zmíněný předchozí článek. Jak je vidět, cachujeme zde MemoryStream (můžeme si jej představit jako pole bajtů v paměti), ten je totiž výsledkem vygenerování obrázku formátu PNG z bitmapy. Na začátku se pokusíme vyjmout data obrázku z cache, pokud se to nepodaří, vygenerujeme nová data a zároveň je vložíme do cache. Pokud se data podaří z cache vyjmout, rovnou je použijeme pro výstup (žádné generování se neprovádí).

Všimněte si explicitních direktiv stránky EnableViewState="False", EnableSessionState="False", Trace="False", Debug="False". Od této aplikace požadujeme co největší rychlost, naopak sledování session nebo viestate vůbec nepotřebujeme, stejně jako ladící informace nebo výpis trasování. Protože nevím, v působnosti jakého nadřízeného „web.config“ se naše aplikace může ocitnout, je lépe zde explicitně nepotřebné volby vypnout.

Na závěr mám jeden tip pro odzkoušení a ladění aplikace – dočasně si zapněte trasování, zakomentujte dosavadní výstup pomocí Response a doplňte si výstup Trace.Write (nebo Trace.Warn) do části, kde se generuje memorystream a do části, kde se memory stream vyjme z cache. Při prvním načtení stránky uvidíte, že se vypíše text zadaný ve větvi, kde se obrázek generuje, při dalších voláních se již bude vypisovat jen text zadaný ve větvi, kde se data vybírají z cache.

<%@Page Language=“C#“ EnableViewState=“False“ EnableSessionState=“False“ Trace=“True“ Debug=“False“ %>
.
.
{
  PngStream=(MemoryStream) Cache[HeadingText];
  Trace.Warn(„Vybráno z cache!“);
}
else
{
.
.
  Cache.Insert(HeadingText,PngStream);
  Trace.Write(„Vloženo do cache…“);
}
// Response.ClearContent();
// Response.ContentType = „image/png“;
// Response.BinaryWrite(PngStream.GetBuffer());
PngStream.Close();
// Response.End();

Při testování nezapomeňte aplikaci předat v parametru „text“ řetězec, který se má vygenerovat do obrázku. (V souboru ke stažení máte oba dva příklady připraveny k vyzkoušení.)

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět