Non so perché ma il ViewState è un mio pallino e mi cattura molto l'idea che ci sta dietro. Quindi vi parlo di cosa è cambiato in ASP.NET 2.
ASP.NET 1.x
Per farlo bisogna partire da cosa c'è adesso. Come saprete ogni Control ha un metodo SaveViewState che dobbiamo sovrascrivere per persistere le informazioni durante i postbacks. Il metodo base salva ciò che è contenuto nello StateBag fornito dalla proprietà ViewState, quindi spesso si ricorre a salvare elementi in questo hashtable (che piace tanto tanto a Paolo :-D). Tutto questo viene fatto ricorsivamente per tutto l'albero degli oggetti. Una volta terminato, tramite la classe LosFormatter il tutto viene serializzato in stringa e convertito in Base64 per poter esserito inserito nel value del campo nascosto __VIEWSTATE.
L'unico mezzo che abbiamo per modificare cosa e dove persistere è sovrascrivere Page.SavePageStateToPersistenceMedium / LoadPageStateFromPersistenceMedium. Il LosFormatter lavora in modo da prendere l'intero grafo di oggetti e ricorsivamente serializzare ogni oggetto con una sua formattazione particolare. Consiste infatti nell'indicare con una lettera il tipo primitivo o conosciuto e tra < > mettere il valore a seconda del tipo. Per esempio un intero di valore 5 verrà trasformato in i<5>.
Eccovi una tabella del lavoro che fa
Tipo | Prefisso | Valore |
intero | i | numero |
bool | o | t oppure f |
arraylist | l | valori separati da punto e virgola |
hashtable | h | chiave ; valore ; |
pair | p | valore ; valore |
triplet | t | valore ; valore ; valore |
arraystringhe | @ | valori separati da punto e virgola |
array | @ | id del tipo numerico < valori separati da ; > |
altri tipi | b | sottoserializzazione nello stesso modo. Se possiede un TypeConverter usa ConvertTo(stringa) e ConvertFrom(stringa) |
Le classi Pair e Triplet sono state create per velocizzare il lavoro e perché occupanti meno spazio rispetto ad un array. Ecco perché nel controlli del Framework se ne fa ampio uso. La sottoserializzazione avviene annidando i valori; per esempio questo oggetto:
new Pair("ciao", new Pair(2,3))
diventerà: p<ciao;p<i<2>;i<3>>>
Successivamente come già detto tutto questo viene convertito in Base64. La conversione consiste nel racchiudere un set di bytes che vanno da un range di 0 a 255 in un set di bytes che vanno da 0 a 63 e corrispondenti a caratteri trasportabili (dalla A-Z0-9+=) della tabella ASCII US. Questa operazione comporta però un aumento dei bytes in ingresso di circa un terzo.
ASP.NET 2
Come già anticipato da Marco, il ViewState è stato affiancato dal Control State. Non c'è nessuna differenza tra i due. Entrambi infatti verrano uniti tramite un Pair di root e verranno serializzati insieme. C'ho che cambia è lo scopo: salvare le informazioni minime per il funzionamento del controllo. La particolarità sta nel fatto che per salvare delle informazioni in questo "bag" dovremo sovrascrivere Control.SaveControlState, ma che questo non viene più fatto ricorsivamente. Ad indicare che il controlstate deve essere usato pochissimo, anzi, molti controlli non ne fanno uso. Infatti è necessario notificare alla Page che abbiamo bisogno di persistere queste informazioni tramite Page.RegisterRequireControlState.
Tutto questo verrà serializzato e persistito tramite Page.PageStatePersister una proprietà che possiamo sovrascrivere e che dispone di due implementazioni: HiddenFieldPageStatePersister e SessionStatePageStatePersister. I nomi dicono già tutto: il primo serializza e butta il tutto nel campo nascosto __VIEWSTATE e l'altro persiste nella session senza riempire la pagina da restituire al client.
L'aspetto interessante è che la scelta viene fatta sfruttando gli adaptive rendering. Per dispositivi mobile è configurato infatti di utilizzare il persister su sessione.
Ora LosFormatter è stato sostiuito (seppure presente per motivi di retrocompatibilità) da ObjectStateFormatter. La prima differenza sta nel fatto che non vengono più usati il < > per racchiudere un oggetto e non sono più annidati, ma "concatenati" uno dopo l'altro. Questo porta ad una riduzione dei bytes utilizzati specialmente se gli oggetti sono tanti. Inoltre il prefisso è stato sostituito da un byte progressivo che parte da 100 (0x65) ad indicare la tipologia di dato serializzato. Questa scelta mi sembra essere solo stilistica e fine a nient'altro, magari mi sfugge qualcosa. La gamma dei tipi conosciuti è stata ulteriorermente migliorata ed estesa a tipi come: Unit, Char, DateTime, Color, Type. Questo per ridurre al minimo la trasformazione in stringa essendo tipi di uso comune.
Una classe importante è IndexedString. Qualora il formatter trovi nel grafo degli oggetti di questo tipo ed è la prima volta che lo incontra, memorizza il valore in un hashtable e scriverà in output (byte)5 + stringa. La volta successiva invece scriverà (byte)31 indice di posizione dell'hashtable. In questo modo indicizza e non ripete più volte il valore. Questa classe viene sfruttata quando la proprietà Control.ViewState deve essere persistita.
Tutto questo verrà poi convertito come in .NET 1.x in Base64.
Il risultato di tutto questo è una maggiore compressione del ViewState specialmente con una struttura d'albero complessa e con molti oggetti.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- Silverlight e versioni CLR, il 28 agosto 2007 alle 13:49
- Intercettare il reciclo di un'applicazione ASP.NET, il 25 settembre 2006 alle 22:42
- User e custom controls, WebParts, il 15 giugno 2006 alle 20:52
- Capitolo 10 tutto su ObjectDataSource, il 6 giugno 2006 alle 23:03
- ASP.NET 2.0 per tutti: capitolo 9 pronto, il 28 maggio 2006 alle 22:55
- Gestione dei Threads in ASP.NET, il 19 aprile 2006 alle 21:36