Mantenere lo stato e passare informazioni tra pagine - prima parte

Le applicazioni web utilizzano il protocollo http il quale è "senza memoria": ogni volta che un client (di solito un browser) fa una richiesta al server web, questa viene interpretata come una nuova richiesta. La pagina viene servita e le risorse vengono liberate. Ciò permette al server di gestire un numero elevato di richieste simultanee.

L'utente finale però ha l'illusione che l'applicazione web continui a girare come se si trattasse di una applicazione desktop installata sul proprio pc. Per ottenere questo risultato si usano diverse tecniche che permettono sia di mantenere lo stato in una singola pagina o in tutte le pagine, sia di trasmettere informazioni da una pagina all'altra. 

ViewState

Il ViewState è una prerogativa di Asp.Net. E' limitato alla singola pagina ed è la tecnica ideale per mantenere informazioni tra un postback e l'altro. Viene infatti usato dai controlli per mantenerne lo stato, ad esempio per mantenere il testo contenuto in una texbox quando si preme un pulsante che genera un postback.

In pratica si tratta di un campo form nascosto il cui codice html viene generato automaticamente da Asp.Net.
Ecco un esempio:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
       value="/wEPDwUKMTY2MzUzNzc4NWRko+Xtp73ghhULVy0PkKlfxwP04+HUkLqqp8o/0X0Ajg8=" />

Questa stringa incomprensibile non è cifrata quindi il ViewState non viene usato per memorizzare informazioni riservate.

E' possibile inserire variabili manualmente, che possono essere anche di tipo complesso:

Me.ViewState("saluto") = "ciao"
ViewState("tipo") = 100

Per leggerle basta usare la notazione ViewState("nomeVariabile"). In questo esempio le ho convertite in stringa per visualizzarle in una ListBox

lstVariabili.Items.Add("Saluto: " & CType(ViewState("saluto"), String))
lstVariabili.Items.Add("Tipo: " & ViewState("tipo").ToString)

Ottimizzare il ViewState

Se si inseriscono troppe informazioni nel ViewState si appesantisce il peso in KiloByte della pagina in quanto ad ogni postback vengono ritrasmesse tutte le informazioni al server e viceversa.
Quando una pagina non ha affatto bisogno di mantenere lo stato dei controlli è possibile disattivare il ViewState a livello di pagina aggiungendo un attributo alla direttiva Page:

<%@ Page Title="Dev-oClock" Language="VB" EnableViewState="false" %>

In alternativa è possibile disattivare il ViewState sui singoli controlli:

<asp:TextBox ID="TextBox1" runat="server" ViewStateMode="Disabled"></asp:TextBox>

In entrambi i casi si vedrà una notevole riduzione della stringa nel campo hidden della pagina.

QueryString (metodo Get)

La tecnica del QueryString consiste nel richiamare una pagina web trasmettendo parametri direttamente nell'indirizzo URL.
Questo è un esempio di Url nel quale si richiama una pagina passando l'id del prodotto:

http://www.dev-oclock.com/scheda-prodotto.aspx?id=7&mode=viewall

Il parametro id può essere usato dalla pagina per capire quale prodotto mostrare e gli altri parametri possono dare altre direttive.

Si possono quindi trasmettere dati in formato stringa e direttamente visibili dall'utente finale.
Il vantaggio è che questi indirizzi vengono memorizzati dai crawler dei motori di ricerca e trattati come singole pagine del sito. E' pertanto controproduttivo fare un uso eccessivo di JavaScript/Ajax in un sito pubblico seo-friendly ma è meglio tenere indirizzi Url ben distinti anche grazie ai parametri di querystring.

Codifica degli indirizzi

A volte è necessario passare in Get stringhe contenti caratteri particolari che non sono ammessi nell'Url di una pagina web oppure che hanno già funzione di separatore. Alcuni di questi caratteri sono lo slash (/), il punto di domanda e la "e commerciale" (&).
In queso caso è necessario operare una codifica della stringa usando il comando Server.UrlEncode

Dim strTesto As String = "inizio_    !!! &+???:\|/< fine_"
strTesto = Server.UrlEncode(strTesto)

Dim strUrl As String
strUrl = "QueryString_2.aspx?id=1&action=ok&testo=" & strTesto

Response.Redirect(strUrl, True)

In questo esempio la stringa strTesto viene convertita e si ottiene una quesrystring accettabile:

QueryString_2.aspx?id=1&action=ok&testo=inizio_++++!!!+%26%2b%3f%3f%3f%3a%5c%7c%2f%3C+fine_

La pagina di destinazione potrà leggere indistintamente i parametri codificati e quelli non codificati senza bisogno di effettuare alcuna decodifica:

Request.QueryString("id")
Request.QueryString("action")
Request.QueryString("testo")

Cross-page postback (metodo Post)

Post è un altro metodo per trasmettere dati da una pagina ad un'altra. In questo caso i parametri vengono trasmessi nell'intestazione della richiesta.

Asp.Net fornisce la possibilità di fare un postback ad un'altra pagina anziché alla pagina stessa. E' sufficiente impostare  l'indirizzo della pagina di destinazione nella proprietà PostBackUrl del controllo che genera il postback. In qesto modo vengono trasmessi in post tutti i valori dei campi di input compreso il campo nascosto contenente il ViewState.
In questo modo però i controlli non sono direttamente accessibili alla pagina di destinazione; risulta comodo creare delle proprietà pubbliche nella pagina che trasmette i dati, che saranno visibili dalla pagina che riceve i dati. La comodità sta nel fatto che in caso di modifiche sarà sufficiente mettere mano solo al codice della prima pagina.

Esempio:

Questo è un form contenente due caselle di testo e un pulsante nel quale è impostata la proprietà PostBackUrl.

<form id="form1" runat="server">
  <div>
  Nome: <asp:TextBox ID="txtNome" runat="server"></asp:TextBox><br />
  Cognome: <asp:TextBox ID="txtCognome" runat="server"></asp:TextBox><br />
  <asp:Button ID="btnCrossPagePostBack" runat="server" Text="Cross Page Post Back"
          PostBackUrl="post_2.aspx" />
  </div>
</form>

Questa è una proprietà definita all'interno della stessa pagina o nel code behind. Non fa altro che leggere e concatenare i valori delle due caselle.

Public ReadOnly Property NomeCompleto() As String
  Get
    Return txtNome.Text & " " & txtCognome.Text
  End Get
End Property

La pagina di destinazione potrà sfruttare la proprietà per leggere i dati della prima pagina.

If PreviousPage IsNot Nothing Then
	lblNomeCompleto.Text = PreviousPage.NomeCompleto
End If

Se doveste riscontrare errori, provate a usare la tecnica esposta su msdn.

 


La seconda parte dell'articolo illustra altri modi per mantenere lo stato e passare dati da una pagina web ad un'altra.

Autore: Sergio Roberto Boarina