Come sappiamo, il protocollo HTTP è di tipo state-less, ossia senza stato. Ciò vuol dire che non è possibile mantenere delle informazioni di stato tra una richiesta e l’altra, cioè ciascuna richiesta è completamente indipendente dalla precedente.
Con ASP.NET è stato introdotto il meccanismo del ViewState per superare questo limite. Oltre a poter essere abilitato o disabilitato a livello di pagina, è possibile anche gestirlo a livello di singolo controllo attraverso l’attributo EnableViewState.
Ci sono, però, alcuni controlli per i quali, pur settando EnableViewState = false, il loro valore viene mantenuto in seguito ad un Postback. Uno di questi è la semplicissima TextBox. Come è possibile ciò ?
Consideriamo una pagina aspx nella quale abbiamo una TextBox ed un Button.
<asp:TextBox ID="MyTextBox" runat="server" EnableViewState="false"/>
<asp:Button ID="MyButton" runat="server" Text="Click" onclick="MyButton_Click" />
Osserviamo che ho volutamente settato EnableViewState = false per il controllo TextBox. Se visualizziamo la pagina per la prima volta, avremo il seguente risultato.
Sino a qui non c’è nulla di strano; proviamo però a digitare del testo nella TextBox e cliccare sul bottone in modo da eseguire un Postback alla pagina. Pur non avendo abilitato l’uso delViewState sulla TextBox, il risultato sarà il seguente.
Come è possibile ciò ? In che modo lo stato del controllo è stato mantenuto pur avendo disabilitato la gestione del ViewState ?
Ebbene, la risposta è semplice; il controllo TextBox fa parte di un gruppo di controlli che implementano l’interfaccia IPostBackDataHandler e per i quali il valore immesso dall’utente viene trasferito attraverso l’header HTTP della richiesta POST al server e non viene immesso nel valore del campo hidden __VIEWSTATE.
Per rendercene conto, consideriamo una parte dell’HTML della pagina appena visualizzata…
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNDQ4MjgxMTgxZGTNOC5r+KAS/pEPhvuwtdjw6Xg+DdjKydHf4P3AT9X6Rw==" />
</div>
<div class="aspNetHidden">
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwKy+bGFCQL1vtaTBwK4ooke2vLPwEEWgJUPhhabX+TyTbj9KOi3hO+pZVItu7X/OoU=" />
</div>
<div>
<input name="MyTextBox" type="text" value="Paolo" id="MyTextBox" />
<input type="submit" name="MyButton" value="Click" id="MyButton" />
…ed utilizzando Wireshark, analizziamo il contenuto della richiesta HTTP POST eseguita verso il server al momento del Postback.
Come si può osservare, al server viene trasmesso il valore del __VIEWSTATE ed a parte il valore immesso nella TextBox come un normale campo INPUT di una form.
In realtà, però, la proprietà Text della classe TextBox è implementata nel modo seguente.
public string Text
{
get
{
string text=(string)ViewState["Text"];
return (text==null)? String.Empty : text;
}
set
{
ViewState["Text"]=value;
}
}
Ciò vuol dire che in fase di salvataggio e caricamento del valore di Text, comunque viene utilizzato il ViewState, indipendentemente dal fatto che esso sia abilitato o meno. Inoltre, laTextBox implementa il metodo LoadPostData dell’interfaccia IPostBackDataHandler attraverso il quale carica il valore immesso ricavandolo dalla collection dei dati post della form.
bool IPostBackDataHandler.LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
// recupera il valore dal ViewState
string text1 = this.Text;
// recupera il valore dalla collection post della form
string text2 = postCollection[postDataKey];
if (!text1.Equals(text2))
{
this.Text = text2;
return true;
}
return false;
}