Posts
103
Comments
238
Trackbacks
4
TextBox, CheckBox e ViewState

Mi sono accorto casualmente di una cosa che non avevo mai notato, e che magari invece molti sanno...
Alcuni controlli lato server, diciamo semplici, così come TextBox e CheckBox, mantengono il loro stato anche se il ViewState è disabilitato, indipendentemente dal fatto che sia disabilitato a livello di macchina, applicazione, pagina o singolo controllo.

Ma non mi avevano insegnato che i controlli mantengono il loro stato solo se il ViewState è abilitato?!

Non mettetevi a ridere, ma io proprio non riuscivo a capire perchè quel cavolo di TextBox continuasse a mostrarmi quello che ci avevo scritto dentro anche dopo un postback, e anche se avevo disabilitato il ViewState.
Va beh, ho pensato, sarò suonato io e - visto che sono, ahimè, autodidatta - mi sarò perso qualcosa.

Allora apro il mio TcpTrace e vedo un pò che succede, mi creo una WebForm semplicissima (WebForm1.aspx), ci metto dentro un TextBox, una DrodDownList e un Button, tutti WebControls, disabilito il ViewState a livello di pagina e mi guardo la risposta.
Anche dopo un PostBack nell'html della pagina non c'è traccia del valore inserito nel TextBox, eppure questo si ricordava benissimo quello che avevo scritto!

Poi mi sfugge l'occhio sull'header della richiesta... c'è qualcosa di troppo... ed ecco svelato il mistero!

Ecco allora che ho fatto due esperimenti, uno col ViewState abilitato ed uno col ViewState disabilitato (a livello di pagina) e mi sono guardato un pò le richieste e le risposte senza e con PostBack, ed ecco i dati.

WebForm1.aspx: la pagina che ho creato; contiene semplicemente un TextBox, una DropDownList, e un Button per fare il PostBack

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="NewsletterMdb.WebForm1" %>
<
!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<
html>
    <
head>
        <
title>WebForm1</title>
        <
meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        <
meta content="C#" name="CODE_LANGUAGE">
        <
meta content="JavaScript" name="vs_defaultClientScript">
        <
meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    <
/head>
    <
body>
        <
form id="Form1" method="post" runat="server">
            id="TextBox1" runat="server"></asp:textbox>
            id="Button1" runat="server" Text="Button"></asp:button>
            id="DropDownList1" runat="server"></asp:dropdownlist>
        <
/form>
    <
/body>
<
/html>

WebForm1.aspx.cs: il code behind della pagina, al primo giro riempo la DropDownList con un pò di valori, per vedere se il ViewState funziona

namespace NewsletterMdb
{
    
/// 
    /// Summary description for WebForm1.
    
/// 

    
public class WebForm1 : System.Web.UI.Page
    {
        
protected System.Web.UI.WebControls.TextBox TextBox1;
        
protected System.Web.UI.WebControls.DropDownList DropDownList1;
        
protected System.Web.UI.WebControls.Button Button1;
    
        
private void Page_Load(object sender, System.EventArgs e)
        {
            
if(!IsPostBack)
            {
                DropDownList1.Items.Add("ciao");
                DropDownList1.Items.Add("ciaoo");
                DropDownList1.Items.Add("ciaooo");
                DropDownList1.Items.Add("ciaoooo");
            }
        }
    }
}

ViewState abilitato

  • Prima Richiesta (!IsPostBack)
GET /NewsletterMdb/WebForm1.aspx HTTP/1.1
Host: localhost:8080
Cookie: ASP.NET_SessionId=ff4g3eet10pdaaiajfe2of45

Niente di interessante, faccio una richiesta di tipo GET inviando il cookie che identifica la sessione, niente di nuovo.

  • Prima Risposta
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Mon, 21 Nov 2005 15:02:13 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 1375


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<
html>
    <
head>
        <
title>WebForm1</title>
        <
meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        <
meta content="C#" name="CODE_LANGUAGE">
        <
meta content="JavaScript" name="vs_defaultClientScript">
        <
meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    <
/head>
    <
body MS_POSITIONING="GridLayout">
        <
form name="Form1" method="post" action="WebForm1.aspx" id="Form1">
<
input type="hidden" name="__VIEWSTATE" value="dDw5MTcxMTIyNTU7dDw7bDxpPDE+Oz47bDx0PDtsP
Gk8NT47PjtsPHQ8dDw7cDxsPGk8MD47aTwxPjtpPDI+O2k8Mz47PjtsPHA8Y2lhbztjaWFvPjtwPGNpYW9vO2NpYW9v
PjtwPGNpYW9vbztjaWFvb28+O3A8Y2lhb29vbztjaWFvb29vPjs+Pjs+Ozs+Oz4+Oz4+Oz5uwu/NsC0rEFZoJatVVOokgkGexA==" 
/>

            <
input name="TextBox1" type="text" id="TextBox1" trackviewstate="false" />
            <
input type="submit" name="Button1" value="Button" id="Button1" />
            <
select name="DropDownList1" id="DropDownList1" >
                <
option value="ciao">ciao</option>
                <
option value="ciaoo">ciaoo</option>
                <
option value="ciaooo">ciaooo</option>
                <
option value="ciaoooo">ciaoooo</option>
            <
/select>
        <
/form>
    <
/body>
<
/html>

ViewState decodificato:

version="1.0" encoding="utf-16"?>

  
    
917112255</string>
    
      
      <
/string>
      
        
1</Int32>
      <
/arrayList>
      
        
          
          <
/string>
          
            
5</Int32>
          <
/arrayList>
          
            
              
                
                <
/string>
                
                  
                    
0</Int32>
                    
1</Int32>
                    
2</Int32>
                    
3</Int32>
                  <
/arrayList>
                  
                    
                      
ciao</string>
                      
ciao</string>
                    <
/pair>
                    
                      
ciaoo</string>
                      
ciaoo</string>
                    <
/pair>
                    
                      
ciaooo</string>
                      
ciaooo</string>
                    <
/pair>
                    
                      
ciaoooo</string>
                      
ciaoooo</string>
                    <
/pair>
                  <
/arrayList>
                <
/pair>
                
                <
/string>
              <
/triplet>
              
              <
/string>
              
              <
/string>
            <
/triplet>
          <
/arrayList>
        <
/triplet>
      <
/arrayList>
    <
/triplet>
    
    <
/string>
  <
/triplet>
<
/viewstate>

Anche qui niente di nuovo, il ViewState contiene i dati della DropownList, così al giro successivo non devo riempirla nuovamente.

  • Seconda Richiesta (IsPostBack tramite il Button) [scrivo "hello" nel TextBox]
POST /NewsletterMdb/WebForm1.aspx HTTP/1.0
Accept: */*
Referer: http://localhost:8080/NewsletterMdb/WebForm1.aspx
Host: localhost:8080
Content-Length: 315
Cookie: ASP.NET_SessionId=ff4g3eet10pdaaiajfe2of45

__VIEWSTATE=dDw5MTcxMTIyNTU7dDw7bDxpPDE%2BOz47bDx0PDtsPGk8NT47PjtsPHQ8
dDw7cDxsPGk8MD47aTwxPjtpPDI%2BO2k8Mz47PjtsPHA8Y2lhbztjaWFvPjtwPGNpYW9vO2Np
YW9vPjtwPGNpYW9vbztjaWFvb28%2BO3A8Y2lhb29vbztjaWFvb29vPjs%2BPjs%2BOzs%2BOz4
%2BOz4%2BOz5uwu%2FNsC0rEFZoJatVVOokgkGexA%3D%3D
&TextBox1=hello&Button1=Button&DropDownList1=ciao

Mmh, interessante, i valori del TextBox e della DropDownList non sono codificati all'interno del ViewState...procediamo...

  • Seconda risposta
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Mon, 21 Nov 2005 15:37:01 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 1409


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<
html>
    <
head>
        <
title>WebForm1</title>
        <
meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        <
meta content="C#" name="CODE_LANGUAGE">
        <
meta content="JavaScript" name="vs_defaultClientScript">
        <
meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    <
/head>
    <
body MS_POSITIONING="GridLayout">
        <
form name="Form1" method="post" action="WebForm1.aspx" id="Form1">
<
input type="hidden" name="__VIEWSTATE" value="dDw5MTcxMTIyNTU7dDw7bDxpPDE+Oz47bDx0PDts
PGk8NT47PjtsPHQ8dDw7cDxsPGk8MD47aTwxPjtpPDI+O2k8Mz47PjtsPHA8Y2lhbztjaWFvPjtwPGNpYW9vO2NpYW9v
PjtwPGNpYW9vbztjaWFvb28+O3A8Y2lhb29vbztjaWFvb29vPjs+Pjs+Ozs+Oz4+Oz4+Oz5uwu/NsC0rEFZoJatVVOokgkGexA==" 
/>

            <
input name="TextBox1" type="text" value="hello" id="TextBox1" />
            <
input type="submit" name="Button1" value="Button" id="Button1" />
            <
select name="DropDownList1" id="DropDownList1" >
    <
option selected="selected" value="ciao">ciao</option>
    <
option value="ciaoo">ciaoo</option>
    <
option value="ciaooo">ciaooo</option>
    <
option value="ciaoooo">ciaoooo</option>

<
/select></form>
    <
/body>
<
/html>

ViewState decodificato: è lo stesso della risposta precedente (e lo stesso di questa richiesta, eccezion fatta per i valori in chiaro di TextBox e DropDownList)

Eccoci qui, il ViewState non contiene niente a proposito del testo inserito nel TextBox e del valore selezionato della DropDownList, ed oltretutto è lo stesso della prima risposta, eppure questi hanno mantenuto il loro valore! Accade perchè il loro valore, pur non comparendo nel ViewState, è stato inviato al server nell'header della richiesta!! Quindi alla risposta il loro valore è ripristinato, ma il ViewState della pagina contiene soltanto la Collection di oggetti della DropDownList.

Beh, in verità questo non è niente di nuovo rispetto a quello che ci aspettavamo, dopotutto il ViewState qui è abilitato...ma cosa succede se disabilitiamo il ViewState? Ho ripercorso i passi appena fatti (richiesta - risposta - postback - risposta) disabilitandolo (sempre a livello di pagina).

ViewState Disabilitato

  • Prima richiesta (!IsPostBack)
GET /NewsletterMdb/WebForm1.aspx HTTP/1.0
Host: localhost:8080
Cookie: ASP.NET_SessionId=ueozj2bwrqcp0w33wlenuwuz

Niente di interessante.

  • Prima risposta
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Mon, 21 Nov 2005 15:45:35 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 1168


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<
html>
    <
head>
        <
title>WebForm1</title>
        <
meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        <
meta content="C#" name="CODE_LANGUAGE">
        <
meta content="JavaScript" name="vs_defaultClientScript">
        <
meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    <
/head>
    <
body MS_POSITIONING="GridLayout">
        <
form name="Form1" method="post" action="WebForm1.aspx" id="Form1">
<
input type="hidden" name="__VIEWSTATE" value="dDw5MTcxMTIyNTU7Oz5yvBprsfqzgIoUHU+7HZMA9E2I0g==" />

            <
input name="TextBox1" type="text" id="TextBox1" />
            <
input type="submit" name="Button1" value="Button" id="Button1" />
            <
select name="DropDownList1" id="DropDownList1">
    <
option value="ciao">ciao</option>
    <
option value="ciaoo">ciaoo</option>
    <
option value="ciaooo">ciaooo</option>
    <
option value="ciaoooo">ciaoooo</option>

<
/select></form>
    <
/body>
<
/html>

ViewState decodificato:

version="1.0" encoding="utf-16"?>

  
    
917112255</string>
    
    <
/string>
    
    <
/string>
  <
/triplet>
<
/viewstate>

E' quello che ci aspettavamo, nel ViewState non è conservata la Collection di valori della DropDownList, quindi, al prossimo giro, la perderemo

  • Seconda Richiesta (IsPostBack tramite il Button) [scrivo "hello" nel TextBox]
POST /NewsletterMdb/WebForm1.aspx HTTP/1.0
Referer: http://localhost:8080/NewsletterMdb/WebForm1.aspx
Host: localhost:8080
Content-Length: 115
Cookie: ASP.NET_SessionId=ueozj2bwrqcp0w33wlenuwuz

__VIEWSTATE=dDw5MTcxMTIyNTU7Oz5yvBprsfqzgIoUHU%2B7HZMA9E2I0g%3D%3D
&TextBox1=hello&Button1=Button&DropDownList1=ciao

Mmh...beh in fondo è giusto che il browser invii al server i dati della form, ma il server poi che uso ne fa? Vediamo...

  • Seconda risposta
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Mon, 21 Nov 2005 15:50:30 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 1022


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<
html>
    <
head>
        <
title>WebForm1</title>
        <
meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        <
meta content="C#" name="CODE_LANGUAGE">
        <
meta content="JavaScript" name="vs_defaultClientScript">
        <
meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    <
/head>
    <
body MS_POSITIONING="GridLayout">
        <
form name="Form1" method="post" action="WebForm1.aspx" id="Form1">
<
input type="hidden" name="__VIEWSTATE" value="dDw5MTcxMTIyNTU7Oz5yvBprsfqzgIoUHU+7HZMA9E2I0g==" />

            <
input name="TextBox1" type="text" value="hello" id="TextBox1" />
            <
input type="submit" name="Button1" value="Button" id="Button1" />
            <
select name="DropDownList1" id="DropDownList1"></select>
        <
/form>
    <
/body>
<
/html>

ViewState decodificato: è lo stesso della prima risposta.

Eccoci infine...ho postato la form al server, inviandogli giustamente i dati, e lui che ne ha fatto? Me li ha rimandati indietro anche se avevo il ViewState disabilitato! Questo naturalmente solo per il TextBox...o meglio, l'avrebbe fatto anche per la DropDownList se io avessi ricreato la lista dei valori, cosa che non ho fatto, e che col ViewState disabilitato è andata persa.

Conclusione: alcuni controlli server, come TextBox, CheckBox e tutti quelli mostrati nella figura seguente, non mantengono il loro stato nel ViewState, quindi, anche se questo è disabilitato, il loro stato viene ripristinato ad ogni roundtrip.

A meno di aver detto delle grosse castronerie, quindi, una domanda mi sorge spontanea: a cosa serve il ViewState in questi controlli??

Source: Viewstate Optimization Strategies in ASP.NET

powered by IMHO 1.3

posted on Monday, November 21, 2005 5:33 PM Print
News

Scopri CS2, il mio progetto universitario per l'indicizzazione e la ricerca di codice sorgente personale costruito su Lucene.Net.

Windows Developer Power Tools

Potete trovare il mio progetto BusyBoxDotNet nel libro Windows Developer Power Tools, pubblicato da O'Reilly, per il quale ho scritto l'intero capito dedicato.

Sono stato nominato dVP 2008, un riconoscimento per l'apporto fornito alla comunità del progetto db4o.