ASP.NET 2.0 Page State Persister

 

Matt Gibbs
Development Lead, Web Platform and Tools

Dicembre 2005

Relativo a:
ASP.NET 2.0
Visual Studio 2005

Riassunto: ASP.NET 2.0 aggiunge il supporto per la modifica della posizione in cui vengono memorizzati i dati ViewState relativi alle pagine. In questo articolo viene descritto come è possibile creare una nuova classe da utilizzare per memorizzare le informazioni ViewState in Session invece che nel campo nascosto predefinito (5 pagine stampate).

Gli sviluppatori di controlli ASP.NET utilizzano ViewState e il controllo dello stato per rendere permanenti le informazioni di stato tra le richieste del browser. In genere, queste informazioni vengono trasmesse al client sotto forma di campo nascosto nel tag HTML generato dalla pagina. Questo stato della pagina viene quindi restituito come parte del successivo invio di moduli al server e ripristinato nel controllo o nella pagina. Questo consente agli sviluppatori di controlli di offrire facilmente un migliore utilizzo dell'applicazione sfruttando la possibilità di memorizzare temporaneamente informazioni di stato anche se il browser sta utilizzando il protocollo HTTP, che è privo di stato per definizione.

ASP.NET 2.0 consente di modificare la posizione e la modalità con cui viene reso temporaneamente persistente lo stato della pagina. In alcuni casi, può essere preferibile evitare il ciclo di andata e ritorno dei dati tra client e server. I due persister dello stato della pagina forniti da ASP.NET 2.0 sono il già citato HiddenFieldPageState e SessionPageStatePersister. SessionPageStatePersister utilizza le sessioni server associate alla sessione del browser per memorizzare i dati. L'impiego di SessionPageStatePersister è caratterizzato da pro e contro. L'utilizzo di una sessione invece di un campo nascosto evita un aumento nella dimensione della pagina scambiata con il browser. In molte situazioni, lo stato della pagina costituisce una parte significativa del tag complessivo. Tuttavia, la memorizzazione di questi dati nella sessione consuma preziose risorse del server. Inoltre, ai campi nascosti non è associato un timeout come invece accade per le sessioni. Si potrebbe configurare un'applicazione per rendere persistenti le sessioni in un database di backend ed evitare di porre il carico direttamente sul server Web. Questo consentirebbe anche di scalare verso il basso in scenari Web farm.

Per utilizzare un persister diverso da quello predefinito, si esegue l'override della proprietà PageStatePersister della pagina e si restituisce un'istanza di un altro persister. Per prima cosa, qui viene mostrata una pagina di esempio che riempie un ArrayList con una serie di numero e lo associa quindi a un controllo GridView.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
    protected override PageStatePersister PageStatePersister {
        get {
            return new SessionPageStatePersister(this);
        }
    }
    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);
        if (!IsPostBack) {
            ArrayList list = new ArrayList();
            for (int i = 0; i < 1000; i++)
            {
                list.Add(Convert.ToString(i));
            }
            GridView1.DataSource = list;
            GridView1.DataBind();      
        }
    }
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="GridView1" runat="server" />        
        <asp:Button ID="Button1" runat="server" Text="Submit" /></div>
    </form>
</body>
</html>

Quando si esamina il codice HTML generato per la pagina si può notare un grande campo nascosto per il trasporto di ViewState.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
   Untitled Page
</title></head>
<body>
    <form name="form1" method="post" action="default2.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
value="/wEPDwUKMTQ0MDQzNjk2Ng9kFgICBA9kFgICAQ88KwANAgAPFgYeC18hRGF0YUJv
dW5kZx4JUGFnZUNvdW50AgEeC18hSXRlbUNvdW50AhRkDBQrAAEWBh4EVHlwZRkrAh4ETmF
tZQUESXRlbR4JRGF0YUZpZWxkBQEhFgJmD2QWKgIBD2QWAmYPDxYCHgRUZXh0BQEwZGQCAg
9kFgJmDw8WAh8GBQExZGQCAw9kFgJmDw8WAh8GBQEyZGQCBA9kFgJmDw8WAh8GBQEzZGQCB
Q9kFgJmDw8WAh8GBQE0ZGQCBg9kFgJmDw8WAh8GBQE1ZGQCBw9kFgJmDw8WAh8GBQE2ZGQC
CA9kFgJmDw8WAh8GBQE3ZGQCCQ9kFgJmDw8WAh8GBQE4ZGQCCg9kFgJmDw8WAh8GBQE5ZGQ
CCw9kFgJmDw8WAh8GBQIxMGRkAgwPZBYCZg8PFgIfBgUCMTFkZAIND2QWAmYPDxYCHwYFAj
EyZGQCDg9kFgJmDw8WAh8GBQIxM2RkAg8PZBYCZg8PFgIfBgUCMTRkZAIQD2QWAmYPDxYCH
wYFAjE1ZGQCEQ9kFgJmDw8WAh8GBQIxNmRkAhIPZBYCZg8PFgIfBgUCMTdkZAITD2QWAmYP
DxYCHwYFAjE4ZGQCFA9kFgJmDw8WAh8GBQIxOWRkAhUPDxYCHgdWaXNpYmxlaGRkGAEFCUd
yaWRWaWV3MQ9nZMhHZ3iQZp62S8IR8fTJ5ZL42ira" />
</div>
...

Quando si aggiunge un override alla proprietà PageStatePersister e si utilizza il persister incorporato SessionPageStatePersister, il comportamento della pagina rimane invariato, ma l'archivio utilizzato per i dati sullo stato viene spostato dal campo nascosto allo stato della sessione.

    protected override PageStatePersister PageStatePersister
    {
        get
        {
            return new SessionPageStatePersister(this);
        }
    }

Notare nel sorgente della pagina che il valore del campo nascosto è molto più piccolo, ma non è sparito del tutto. ASP.NET trasporterà comunque qualche set minimo di dati nell'output della pagina.

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
value="/wEPaA8FDzhjNzkyNTMzNjE1YWEyNxgBBQlHcmlkVmlldzEPZ2QZw
44JLJFcglwRl9TiNliE82yAuQ==" />

In alcuni scenari, è possibile aggiungere semplicemente del codice come questo a un piccolo set di pagine, quindi l'aggiunta di un semplice override come questo può risultare accettabile. Nel caso in cui si desideri questo comportamento per un'intera applicazione o per un set di pagine più grande, sarà opportuno orientarsi verso un metodo di controllo più centralizzato. Sono disponibili vari modi per ottenere questo risultato. È possibile spostare il codice che crea il persister nella classe che eredita dalla pagina:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public class PagePersisterBasePage : Page
{
    public PagePersisterBasePage()   {
    }
    protected override PageStatePersister PageStatePersister {
        get {
            return new SessionPageStatePersister(this);
        }
    }
} 

ASP.NET 2.0 consente di specificare un tipo di base per una pagina mediante la direttiva di pagina "Inherits". Il codice generato da ASP.NET per tale pagina eredita quindi dalla pagina di base ed elimina la necessità di codice duplicato in ogni pagina.

<%@ Page Language="C#"  Inherits="PagePersisterBasePage" %>

Inoltre, opzioni di configurazione consentono di impostare una posizione delle pagine in modo che tutte utilizzino un unico tipo di pagina base. In questa pagina web.config, è stato impostato pageBaseType e non è necessario aggiungere l'attributo Inherits ad alcuna pagina per ottenere il comportamento PageStatePersister personalizzato.

<?xml version="1.0"?>
<configuration>
   <system.web>
    <pages pageBaseType="PagePersisterBasePage" />
   </system.web>
</configuration>

La modifica di PageStatePersister non va fatta con leggerezza. Valutare con attenzione l'applicazione e la distribuzione. Esiste un overhead associato al ciclo di andata e ritorno di ViewState in un campo nascosto, ma vi è un consumo diretto di risorse del server per conservare le informazioni di stato in tale posizione. Nell'esempio precedente è anche possibile osservare che è possibile inserire un persister personalizzato per memorizzare lo stato in un'altra posizione come un database backend o nel servizio di stato condiviso di un Web farm. Come è stato dimostrato, è anche possibile controllare il comportamento dell'applicazione in modo centralizzato o pagina per pagina.

 

Informazioni sull'autore

Matt Gibbs è un importante Software Design Engineer nel team di ASP.NET in Microsoft, dove ha collaborato alle tecnologie di sviluppo Web fino dal 1997. Ha scritto in collaborazione vari libri su ASP e ASP.NET.

Mostra: