Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc
Titulní Blogy Fotky Soubory

2P.Knowledge.Blog.API

Ukládání ViewState do Session

View-state patří k vrozeným vlastnostem ASP .NET již od jeho počátku a některými lidmi je milován a jinými zase zatracován. Podle mě je pravda někde mezi a při jeho správném použití může přinést spoustu užitku. Standardně je view-state stránky ukládán ve skrytém políčku formuláře (hidden field), což v případě stránek z mnoha ASP .NET prvky vede ke značné velikosti obsahu tohoto políčka a tím pádem i celé stránky. Nebo může být s touto reprezentací viewstate problém v případě mobilních zařízení.V těchto situacích je vhodné view-state uložit do alternativního úložiště, kterým často bývá session, která jak známo čerpá prostředky serveru.

Již od své první verze ASP .NET disponuje možností definovat vlastní mechanismus persistence view-state stránky pomocí překrytí metod LoadPageStateFromPersistenceMedium a SavePageStateToPersistenceMedium. V takovémto případě implementace persistence view-state je dobré myslet mimo jiné na to, že klient může mít otevřeno více oken prohlížeče a tím pádem není vhodné ukládat view-state všech stránek do session pod stejným klíčem. Řešením může být GUID ve skrytém poli stránky. Také je při překrývání těchto metod dobré myslet na to, kdy data z alternativního uložiště odstranit, aby nedocházelo ke zbytečnému plýtvání zdroji. Problém také vidím v tom, že metoda SavePageStateToPersistenceMedium se nezavolá v případě vyhození výjimky, což je problém při použití AJAX, kdy není přesměrováno na chybovou stránku, ale po zobrazení chyby pomocí javascriptu (což je v ASP .NET AJAX frameworku výchozí) je klientovi umožněn další požadavek, u jehož zpracování ovšem nebude k dispozici view-state.

Na tyto problémy ovšem existuje poměrně jednoduchý lék, který je v ASP .NET, již od zaběhlé verze 2.0, k dispozici. Od ASP .NET 2.0 je možnost persistence view-state v session implementována, avšak je ve výchozím nastavení vypnuta. ASP .NET pro uložení view-state využívá služeb typů odvozených od třídy PageStatePersister, které jsou standardně dva a to HiddenFieldPageStatePersister, který ukládá view-state standardně do skrytého pole a druhým typem je SessionPageStatePersister, jež ukládá viewstate do session. Konkrétní PageStatePersister je pro konkrétní stránku získán přečtením vlastnosti PageStatePersister. Takže uložení viewstate do session se provede jednoduchým překrytím této vlastnosti na stránce a navrácení instance typu SessionPageStatePersister. Pozor na to, že je třeba vracet v rámci stránky stejnou instanci typu PageStatePersister, jinak se mohou vyskytnout problémy (špatné uchovávání hodnot mezi post-backy).

protected override PageStatePersister PageStatePersister
{
  if (statePersister == null)
  {
      statePersister = new SessionPageStatePersister(this);
  }
  return statePersister;
}

V případě, že se nechcete vydat cestou použití dědičnosti stránek, můžete využít podpory adaptivního renderingu, která je k dispozici od ASP .NET 2.0 a vytvořit PageAdapter u něhož je možné překrýt metodu GetStatePersister. Tímto způsobem lze v kombinaci s konfigurací v browser souboru zajistit, že view-state bude v session pouze pro specifická zařízení.

public class MyPageAdapter : PageAdapter
{
    public override PageStatePersister GetStatePersister()
    {
        return new SessionPageStatePersister(this.Page);
    }
}

Použití SessionStatePagePersisteru zařídí uložení view-state do session a do skrytého pole jsou uloženy pouze informace nutné k možné rekonstrukci viewstate ze session. Pro případné otevření více oken ukládá data několika posledních stránek. Výchozím nastavením je hodnota 9, takže když klient otevře desáté okno v tom prvním otevřeném při post-backu nedojde k načtení viewstate. Tuto hodnotu je ovšem možno konfiguračně nastavit v sekci system.web souboru web.config.

<system.web>
    <sessionPageState historySize="10"/>
</system.web>

V mnoha případech ovšem zjistíte, že i přestože je použit SessionPageStatePersister, tak je view-state pořád poměrně velký. Je tomu z důvodu, že control-state, který je od ASP .NET 2.0 přítomen pro zachování fukčnosti ASP .NET prvků i v případě vypnutého view-state je stále ukládán do skrytého pole a to i v případě, že standardní viewstate je v session. V případě řešení, které bylo zmíněno výše, tedy pomocí překrytí metod LoadPageStateFromPersistenceMedium a SavePageStateToPersistenceMedium tento problém nenastává, protože je ukládán view-state i control-state dohromady. Naštěstí je k dispozici řešení i v případě použití elegantějšího SessionPageStatePersisteru a to opět pomocí konfigurace v sekci browserCaps (která je již označena za deprecated, ale jiné řešení jsem nenašel).

<browserCaps>
      <case>RequiresControlStateInSession=true</case>
</browserCaps>

Udělal jsem si malý test s jednoduchou stránkou s prvkem GridView, ve kterém bylo zobrazeno 10 záznamů se 3 sloupci a nastavenou vlastností DataKeyNames na hodnotu ID (hodnoty ID se ukládají do view-state) a tady jsou výsledky velikosti skrytého pole s ID __VIEWSTATE ve stránce :

View-state i Control-state ve skrytém poli - 1440 bajtů
View-state v session a Control-state ve skrytém poli - 352 bajtů
View-state i Control-state v session - 56 bajtů

Zveřejněno 11. ledna 2008 23:35 by Puschak
Vedeno pod: ,

Komentář

 

haken napsal:

Petře, oprav si to... ;-)

Ten override Page.get_PageStatePersister musí vrace stále stejnou instanci, jinak se to vybleje...

http://knowledge-base.havit.cz/asp-net/Jak_2D00_prepsat_2D00_PageStatePersister.aspx

února 20, 2008 23:19
 

Puschak napsal:

Díky za připomínku Roberte, už jsem to opravil. Tak už vím, proč nám na projektu někdy mizeli hodnoty některých vlastností :-) Zajímavé, že to není zmíněno v dokumentaci..

dubna 12, 2008 9:56
Neregistrovaní uživatele nemužou přidávat komentáře.
Powered by Community Server (Personal Edition), by Telligent Systems
Vyvojar.cz na prodej!