Co by měl každý vědět o ViewState

1) ViewState není odpovědný za zachování vlastních hodnot controlů mezi postbacky

ViewState není odpovědný za zachování hodnot (Value) TextBoxů, CheckBoxů, DropDownListů a jiných Web controlů mezi postbacky. Tyto hodnoty jsou uloženy normálně ve formulářových postback datech (POST/GET) a ASP.NET je nastaví v metodě LoadPostData() pro všechny prvky, které implementují rozhraní IPostBackDataHandler. Na to, aby nám mezi roundtripy zůstal text v TextBoxu tedy nepotřebujeme ViewState!!!

2) Na co tedy ViewState?

ViewState je vlastnost každého controlu zděděná od System.Web.UI.Control (má ji tedy i Page) a jeho základní funkčnost je založena ná následující implementaci vlastností:

public string NavigateUrl { get    { string text = (string) ViewState["NavigateUrl"]; if (text != null) return text; else return string.Empty;    } set    {       ViewState["NavigateUrl"] = value;    } }Hodnoty vlastností (property) se tedy ukládají do a čtou z ViewState, veškeré jejich změny se promítají do ViewState.

3) ViewState je typu StateBag

ViewState je typu System.Web.UI.StateBag, která implementuje mj. IDictionary (slouží k ukládání párů klíč-hodnota) a interně používá HybridDictionary.
Důležitou metodou StateBagu je SaveViewState(), která odpovídá za uložení ViewState.
Celý fígl je v tom, že metoda SaveViewState() uloží jenom ty vlastnosti, které se změnily po zavolání metody TrackViewState() .

4) Co se tedy ukládá při uložení ViewState?

Funkčnost ViewState je úzce spojena s life-cyclem stránky a okamžikem volání metody TrackViewState(). Ta je volána na konci události Init každého controlu, a tedy i stránky (pro zjištění, zda-li již byla volána, lze použít property IsTrackingViewState.
Změny properties provedené před koncem události Init každého controlu se tedy s ViewState neukládají, veškeré další změny až do volání metody SaveViewState() (v události SaveViewState) ano.

5) Jak tedy stránka/control s ViewState funguje?

Vezměme si krátký příklad:
<script runat="server"> private void btnSubmit_Click(object sender, EventArgs e)    {       lblMessage.Text = "Goodbye, Everyone!";    } </script> <asp:Label runat="server" ID="lblMessage" Font-Name="Verdana" Text="Hello, World!"></asp:Label><br /> <asp:Button runat="server" Text="Change Message" ID="btnSubmit"></asp:Button><br /> <asp:Button runat="server" Text="Empty Postback"></asp:Button>

Co se stane při první návštěvě stránky:

  1. "Instantiation stage": Nastaví se lblMessage.Text="Hello, World!"
  2. "Load ViewState stage": nic se nestane, není postback
  3. "Save ViewState stage": nic se nestane, nejsou změny ViewState
  4. "Render Stage": Label je renderován s "Hello, World!"

Co se stane při kliku na Change Message tlačítko:

  1. "Instantiation stage": Nastaví se lblMessage.Text="Hello, World!"
  2. "Load ViewState stage": nic se nestane, ViewState stránky je prázdný
  3. "Raise Postback Event": btnSubmit_Click nastaví
  4. lbl.Message="Goodbye, Everyone!"
  5. "Save ViewState stage": property Text od Labelu je uložena do ViewState, protože se změnila (po volání TrackViewState())
  6. "Render Stage": Label je renderován s "Goodbye, everyone!"

Co se stane při kliku na Empty postback tlačítko:

  1. "Instantiation stage": Nastaví se lblMessage.Text="Hello, World!"
  2. "Load ViewState stage": nastaví se lblMessage.Text="Goodbyw, Everyone!" z ViewState
  3. "Save ViewState stage": property Text od Labelu je uložena do ViewState, protože se změnila (po volání TrackViewState())
    "Render Stage": Label je renderován s "Goodbye, everyone!"
Shrnutí & spol.
  1. Do ViewState se ukládají všechny změny v properties controlů provedené po ukončení události Init.
  2. Protože ViewState ukládá pouze vlastnosti controlů a ne controly samotné, musíme dynamicky přidávané controly přidávat při každém postbacku stránky znovu a znovu - nejlépe během události Init (uděláme-li to však i později, metoda .Add() zajistí nahrání ViewState do přidávaných controlů).
  3. U editovatelných DataGridů je vypnutí ViewState docela dřina.
  4. ViewState se ukládá rekurzivně včetně ViewState child-controlů a to v serializované podobě pomocí LOSFormateru.
  5. ViewState lze ukládat i na serveru na disk nebo do databáze pomocí překrytí metod SavePageStateToPersistenceMedium() a LoadViewStateFromPersistenceMedium(), které standardně právě používají hidden-field ___VIEWSTATE. V některém z dalších článků si ukážeme ukládání do Session.
  6. Další možností na zmenšení ViewState je jeho komprese a dekomprese.
  7. ViewState je chráněn před změnami pomocí machine authentication check (MAC), který však pouze kontroluje, je-li ViewState od stejné verze stránky.
  8. ViewState lze i šifrovat, rozhodně se však nedoporučuje pro ukládání citlivých informací

Viz též článek ViewState vs. fáze Init, aneb jak jsem se chytil.

Robert Haken, ASP.NET MVP

Microsoft MVP