HowTo – Guida ASP.NET (Parte 2)


PARTE 2 – CAPITOLO 2 – Web Forms

Grazie alle Web Forms è possibile creare una pagina web utilizzando le stesse interfacce Control-Based delle Windows Applications. In particolare è possibile utilizzare la funzionale ToolBox di Visual Studio per trascinare i controlli direttamente sulla pagina *.aspx e lasciare che sia il programma ad inserire il codice utile a creare il controllo. Sempre utilizzando la modalità “Design” e il tab “Proprietà” è possibile customizzare l’aspetto del controllo e creare nuovi eventi in risposta a particolari condizioni che potrebbero venire a crearsi durante l’utilizzo dell’applicazione (ad esempio, con riferimento ad un bottone, è possibile associare un evento che scatti nel momento in cui l’utente clicca con il mouse sopra il controllo). A questo punto bisogna introdurre una separazione a livello di markup: con ASP.NET è possibile far coesistere nella stessa pagina i classici controlli HTML e i così detti Web Control. Al primo gruppo fanno riferimento i classici tag del linguaggio html (come, ad esempio, “<p>” per indicare un paragrafo). Nello specifico è possibile fare in modo che questi controlli “classici” siano accessibili e modificabili dal codice server-side aggiungendovi il parametro runat=”server” e assegnando ad ognuno di essi un ID univoco con l’attributo id=”testUnicoID”. Con il termine Web Control invece si fa riferimento ad oggetti custom offerti da ASP.NET e nella maggior parte dei casi spesso mappabili ai classici tag HTML. Ad esempio, se voglio inserire un testo non modificabile dall’utente in una pagina *.aspx posso racchiuderlo tra i tag “<p>” e “</p>” oppure utilizzare il Web Control “<asp:Label ID=”mioID” runat=”server” Text=”testo” />”. Fermiamoci un attimo ad analizzare questo controllo: per prima cosa notiamo che la formattazione di base è simile a quella di qualsiasi altro tag, con il capertura “<” e quello di chiusura “>” (in questo caso “/>” perché il tag è chiuso in sé stesso). Dopodiché, come detto poco fa per i tag html, abbiamo la definizione di un ID univoco e l’istruzione, questa volta obbligatoria, che obbliga il compilatore ad elaborare l’oggetto lato server. La proprietà “Text”, così come le altre proprietà che ogni Web Control possiede, consentono un alto livello di personalizzazione (in questo caso permettono di specificare nient’altro che il testo del messaggio che avremmo altrimenti racchiuso tra i tag “<p>” e “</p>”). Quello che ancora non abbiamo detto è che il compilatore, prima di inviare la pagina *.aspx al browser dell’utente, si preoccuperà di esaminare ogni Web Control e di “convertirlo” in una entità HTML classica (in questo caso ad esempio un semplice paragrafo). Il vantaggio sta nel fatto che uno Web Control è più facilmente manipolabile dal linguaggio Server Side e solleva quasi sempre il programmatore dall’onere di verificare che in tutti i browser il contenuto venga renderizzato in modo corretto. È in fatti il compilatore che, in base al browser del visitatore, rielaborerà nel modo migliore possibile i contenuti del Web Control per evitare spiacevoli incompatibilità. In generale, l’uso di tag HTML classici con l’aggiunta dell’ID e dell’istruzione runat=”server” è percorribile nel caso in cui si stia aggiornando una applicazione già esistente (magari non basata in origine su ASP.NET), mentre l’uso dei Web Control è sicuramente consigliato nel caso in cui si stia sviluppando una nuova applicazione. Appare chiaro fin da subito quanto sia possibile realizzare in una Web Application grazie al motore di ASP.NET. Rimane tuttavia invariata una delle più grandi limitazioni presenti nell’originale protocollo http: quello di essere “stateless”. Quando un visitatore viene rediretto da una pagina web ad un’altra tutte le informazioni che aveva inserito nella prima pagina vengono inevitabilmente perse. Questa limitazione è stata pensata agli albori di Internet soprattutto per favorire una scalabilità pressoché infinita, tuttavia risulta quasi impossibile progettare al giorno d’oggi una applicazione web senza memorizzare le informazioni inserite dagli utenti. Questa è una delle principali ragioni per cui sono nati i linguaggi “Server-Side” (come ASP e PHP): grazie all’oggetto form presente su una pagina e alla rielaborazione della stessa da parte del server dopo l’invio del modulo è possibile recuperare i dati presenti nei campi e salvarli (temporaneamente) altrove prima che vengano definitivamente eliminati. ASP.NET non fa eccezione in questo senso. Non è in grado di superare la natura stateless di http ma, nel corso delle sue diverse edizioni, ha fornito agli sviluppatori comodi strumenti per aggirare questo problema e ottenere i dati dell’utente prima che la pagina venga ri-processata. Il metodo più classico, come abbiamo detto, è quello del form. Tutte le pagine aspx che richiedono una qualsiasi interazione con il Server posizionano i loro controlli all’interno dei tag “<form id=”Form1” runat=”server”>” e “</form>”. La dichiarazione di questa struttura può avvenire pagina per pagina oppure, nel caso si stesse utilizzando una Master Page (concetto spiegato di seguito) all’interno della stessa in modo che venga automaticamente posizionata in tutte le pagine che ne ereditano il codice. Per recuperare una variabile presente in un form è possibile ricorrere all’oggetto Request.Form[]. Se in una pagina era presente un form con un campo caratterizzato dall’ID “nome”, il contenuto di tale campo sarà recuperabile, dopo l’invio della pagina stessa, con l’istruzione Request.Form[“nome”]. Riprendiamo ora un concetto già esposto in precedenza: le pagine ASP.NET non vengono “eseguite” dal server riga per riga (come avviene in ASP) ma, aggiungendo i relativi controlli, è possibile decidere programmaticamente a quali eventi devono rispondere. Il meccanismo con il quale ASP.NET si “accorge” di questi eventi è quello del “PostBack”. Un postback non è nient’altro che la replicazione di ciò che avviene quando si preme il classico pulsante “Invia” presente in tutti i form: la pagina viene rispedita al Server che potrà leggere il contenuto dei suoi campi. Al contrario di altri linguaggi, ASP.NET estende il meccanismo di postback a molti controlli, anche diversi dal classico pulsante. In ogni caso, grazie ad alcuni meccanismi che verranno spiegati tra poche righe, ogni volta che viene generato un postback ASP.NET salva una copia dei dati presenti nella pagina e in base alla lettura di questi dati lancia gli eventi associati. Immaginiamo ad esempio una pagina in cui siano presenti un campo di testo ed un pulsante. Al pulsante sarà associato il classico evento “Click()” che genera il postback, mentre al campo di testo è associato un evento che controlla se il testo al suo interno è stato modificato. Durante l’elaborazione del Postback ASP.NET si accorge che il testo contenuto nel campo è diverso da quello che aveva memorizzato in precedenza e decide quindi di eseguire la porzione di codice presente nel metodo “OnTextChanged”. Ad ogni Web Control è possibile associare un cospicuo numero di eventi, che verranno segnalati in automatico da Visual Studio grazie alla funzione di Intellisense. Prima abbiamo detto che ASP.NET estende il meccanismo del postback. Questo avviene grazie alla proprietà AutoPostBack presente in molti controlli (e settata di default a true per i pulsanti). Tutti gli altri controlli hanno questa proprietà settata a false di default, tuttavia aggiungendo alla dichiarazione la voce “AutoPostBack=true” sarà possibile scatenare un postback in corrispondenza di praticamente qualsiasi evento. Pensiamo ad una checkbox: è possibile causare un postback quando questa viene selezionata o desezionata. Oppure, nel caso di una dropdown, è possibile generare il postback quando viene modificata la selezione. Per riassumere: ad ogni controllo sono associabili una grande quantità di eventi che vengono valutati nel momento in cui viene scatenato un postback, azione che viene causata in automatico dopo il click su un pulsante o in modo programmatico interagendo con molti altri controlli (solo quelli appartenenti alla famiglia dei Web Control). Naturalmente un postback richiede un certo carico di lavoro da parte del server che inevitabilmente si tramuta in una (seppur breve) attesa. Per questo motivo la tecnica del postback non è applicabile a tutti gli eventi in generale. Si pensi, ad esempio, a tutte le azioni compiute con il mouse. In una normale applicazione Windows potremmo decidere di eseguire del codice quando il cursore del mouse viene portato all’interno o all’esterno di una certa area. Questo tipo di reazioni sono semplicemente non applicabili quando si ragiona nella logica Client-Server. Per implementare questo tipo di controlli è necessario usufruire di un linguaggio client-side (che viene eseguito direttamente nel browser dell’utente) capace di rispondere in tempo reale agli eventi. Seppur esistano una serie di strumenti capaci di compiere queste operazioni, il linguaggio attualmente più utilizzato per questo scopo è Javascript (a cui si farà un accenno nel primo extra in fondo). Abbiamo detto che ASP.NET offre una metodologia per “aggirare” la natura stateless di html e non perdere i dati immessi dall’utente su una pagina. Lo strumento più importante che realizza questa funzione è chiamato ViewState. Quando un form viene rispedito al server questo effettua delle operazioni e poi ricarica la pagina html originale. Prima di inviarla al client , il server reagisce agli eventuali eventi scatenati sulla pagina ed eventualmente modifica alcuni controlli in seguito a questi eventi. Ma questo non è sufficiente a mantenere lo stato originale della pagina. Il ViewState si preoccupa di memorizzare in una collection il contenuto di ogni controllo e di serializzare il tutto con un encode in Base64 (per evitare i caratteri non validi) all’interno di un campo hidden che viene inviato insieme al form di cui fa parte. Naturalmente questa collecion viene mantenuta costantemente aggiornata in modo da poter essere deserializzata e fornire esattamente il contenuto che era presente in precedenza in ogni controllo. Questa incredibile comodità ci viene offerta da ASP.NET a patto di accettare che il peso della pagina ricevuta aumenti in modo più o meno considerevole: bisogna infatti tenere conto che, come abbiamo detto, il viewstate viene serializzato e deserializzato ad ogni postback grazie ad un campo hidden che, seppur nascosto, deve necessariamente inviare/ricevere dati. Se all’interno di una pagina non c’è ragione per cui un controllo debba memorizzare il suo stato è possibile ridurre (anche sensibilmente) il peso della pagina stessa impostando la proprietà EnableViewState dell’oggetto a false. In questo modo l’oggetto verrà ricreato con le sue caratteristiche originali ogni volta che verrà scatenato un postback. Capita (e non di rado) che, a furia di abusare del ViewState, il contenuto di un campo hidden superi la quota massima imposta da molti Proxy/Firewall. In questo caso è necessario separare il contenuto in due campi di dimensioni più piccole. È possibile abilitare in modo automatico questa funzione (ViewState Chuncking) inserendo la direttiva “” nel file web.config. Un’ultima nota sugli eventi: nelle pagina principali è possibile dichiarare gli eventi come “private” mentre negli user control, per via del livello di accesso fornito dalle partial classes, è necessario dichiararli come protected. Spesso, per questioni di comodità, si usa dichiarare come protected anche i metodi delle pagine principali. Se avete la necessità di trasferire il navigatore su un’altra pagina (e se proprio non riuscite ad aspettare il capitolo sulla gestione dello stato..) basta invocare il metodo Server.Transfer(). Per realizzare collegamenti esterni all’applicazione va invece utilizzata la direttiva Server.Redirect(). Prima di chiudere questo capitolo è utile accennare al fatto che anche la sezione head di una pagina è gestibile come se fosse un controllo: grazie infatti alla direttiva Page.Header e a tutti i suoi metodi/proprietà è possibile modificare programmaticamente il contenuto di tale sezione impostando, ad esempio, un titolo diverso in base alla pagina caricata.

[Omnia / Luca Zaccaro]


Una risposta a “HowTo – Guida ASP.NET (Parte 2)”

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *