Detekce ztráty ViewState při použití SessionPageStatePersisteru

Pokud směřujete ViewState do Session pomocí SessionPageStatePersisteru, pak se dříve nebo později setkáte s problémem ztrát ViewState a s potřebou detekovat a řešit tuto situaci.

Ke ztrátě ViewState může dojít v následujících případech:

  • v případě zániku/vyčištění Session, zejména při jejím timeoutování při nečinosti uživatele – uživatel si například nechá dlouho otevřenou stránku, vyprší mu mezi tím session, následně provede postback a problém je na světě, došlý postback nemá na serveru už ViewState,
  • v případě ztráty InProc Session díky restartování aplikace (deployment nové verze, recyklace poolu, atp.)
  • v případě vypadnutí stránky z fronty SessionPageStatePersisteru – persister omezuje totiž počet uložených ViewState a při uložení dalšího nejstarší vypadávají. Výchozí délka fronty je 9, je možné ji přenastavit na větší ve web.configu elementem sessionPageState, atributem historySize
    • pokud si například uživatel otevře současně 10 oken aplikace, pak pokud se vrátí k prvnímu oknu a provede postback, opět chybí ViewState,
    • pokud uživatel používá tlačítko Zpět browseru, např. pokud máme na stránce grid a každý řádek má na sobě tlačítko Detail, jehož obsluha události dělá redirect na stránku s detaily. Takový uživatel pokud klikne na detail prvního řádku, pak Zpět, druhého řádku, Zpět, … kliknutím na detail desátého řádku už způsobený postback na serveru nemá svůj ViewState (devět ViewState detailů vytlačilo z fronty ViewState stránky s gridem) a problém je zase na světě.

Jak takovou situaci detekovat? …overridováním metody LoadPageStateFromPersistenceMedium() v našich stránkách (obvykle pomocí společného předka všech stránek, nějakého PageBase):

protected override object LoadPageStateFromPersistenceMedium()
{
    // base implementace vrací new Pair(pageStatePersister.ControlState, pageStatePersister.ViewState);
    object pageState = base.LoadPageStateFromPersistenceMedium();

    // ztrátu ViewState můžeme tedy detekovat jako (pair.Second == null)
    // metoda LoadPageStateFromPersistenceMedium se volá jen pro IsPostBack
    Pair pair = pageState as Pair;
    if ((pair != null) && (pair.Second == null))
    {
        Trace.Warn("ViewStateLost !!!");

        FormsAuthentication.RedirectToLoginPage();
    }

    return pageState;
}

Základní (base) implementace metody LoadPageStateFromPersistenceMedium() totiž nedělá celkem nic jiného, než že z použitého persisteru získá ControlState, ViewState a udělá z nich Pair.

Situaci můžeme řešit například tím, že uživatele požádáme o nové přihlášení, či provedeme redirect kamsi do rootu nebo sami na sebe. ViewState už nikde nevydolujeme, musíme z toho nějak vybruslit, aniž bychom uživatele obšťastnili výjimkou NullReferenceException, InvalidFormatException a jinými podobnými, které v takových situacích nastávají.

Napsat komentář

Vyplňte detaily níže nebo klikněte na ikonu pro přihlášení:

WordPress.com Logo

Komentujete pomocí vašeho WordPress.com účtu. Log Out / Změnit )

Twitter picture

Komentujete pomocí vašeho Twitter účtu. Log Out / Změnit )

Facebook photo

Komentujete pomocí vašeho Facebook účtu. Log Out / Změnit )

Google+ photo

Komentujete pomocí vašeho Google+ účtu. Log Out / Změnit )

Připojování k %s