DevExperience

.Net Framework, Embedded Systems & Design Patterns Paolo Patierno's Blog

ASP.NET : TextBox e l’attributo EnableViewState = false

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.

   1: <asp:TextBox ID="MyTextBox" runat="server" EnableViewState="false"/>
   2: <asp:Button ID="MyButton" runat="server" Text="Click" 
   3:             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.

aspnet_viewstate1

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 del ViewState sulla TextBox, il risultato sarà il seguente.

aspnet_viewstate2

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…

   1: <div class="aspNetHidden">
   2: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNDQ4MjgxMTgxZGTNOC5r+KAS/pEPhvuwtdjw6Xg+DdjKydHf4P3AT9X6Rw==" />
   3: </div>
   4:  
   5: <div class="aspNetHidden">
   6:  
   7:     <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwKy+bGFCQL1vtaTBwK4ooke2vLPwEEWgJUPhhabX+TyTbj9KOi3hO+pZVItu7X/OoU=" />
   8: </div>
   9:     <div>
  10:         <input name="MyTextBox" type="text" value="Paolo" id="MyTextBox" />
  11:         <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.

aspnet_viewstate3

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.

   1: public string Text
   2: {
   3:  get
   4:  {
   5:   string text=(string)ViewState["Text"];
   6:   return (text==null)? String.Empty : text;
   7:  }
   8:  set
   9:  {
  10:   ViewState["Text"]=value;
  11:  }
  12: }

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, la TextBox implementa il metodo LoadPostData dell’interfaccia IPostBackDataHandler attraverso il quale carica il valore immesso ricavandolo dalla collection dei dati post della form.

   1: bool IPostBackDataHandler.LoadPostData(string postDataKey, 
   2:                                    NameValueCollection postCollection)
   3: {
   4:     // recupera il valore dal ViewState
   5:     string text1 = this.Text;
   6:     // recupera il valore dalla collection post della form
   7:     string text2 = postCollection[postDataKey];
   8:  
   9:     if (!text1.Equals(text2))
  10:     {
  11:         this.Text = text2;
  12:         return true;
  13:     }
  14:     
  15:     return false;
  16: }
Posted: 30 apr 2011 11:46 da Paolo | con no comments
Inserito sotto: