Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ WEB FORM - Page processing La Web form non è altro che la pagina ASP.NET. Di seguito le nuove caratteristiche: - Strict XHTML rendering. Il codice generato relativa alla Web form è 100% XHTML-compliant. - Predictable client IDs. E' possibile identificare gli oggetti lato client grazie ad ID univoci - Nuova proprietà HtmlHead. Grazie a questa proprietà è ora possibile impostare i meta tag "descrizione" e le parole chiave da codice. - Permanent redirects. ASP.NET consente ora di reindirizzare le richieste con lo stato HTTP codice 301, che indica un redirect permanente. Quando i crawler dei motori di ricerca ottengono questo messaggio, aggiorneranno i loro cataloghi. Anche se ASP.NET consente di scrivere un'applicazione Web in modo molto simile ad un'applicazione Windows, ci sono però delle differenze: - Le applicazioni web sono eseguite sul server. Grazie alla tecnica del postback ASP.NET gestisce questo divario con l'applicazione desktop. Fare un postback significa inviare la pagina (e tutte le informazioni fornite dall'utente) al server, quando vengono eseguite alcune azioni sulla pagina. Una volta che ASP.NET riceve la pagina, si possono sparare i corrispondenti eventi serve-side per notificare il codice. - Le web application sono stateless. Quando una pagina viene renderizzata in HTML, tutti gli oggetti della pagina vengono distrutti e tutte le informazioni specifiche del client vengono scartate. Questo rende difficile ottenere un'esperienza utente senza soluzione di continuità. ASP.NET, però, include diversi strumenti per aiutare a colmare questa lacuna. Il più importante è l'uso del view state, che incorpora automaticamente le informazioni relative alla pagina in un campo nascosto nel rendering HTML della pagina. HTML Forms Il modo più semplice per inviare dati client-side al server è l'uso del tag <form> . Al suo interno è possibile inserire i tag di interfaccia (bottoni, textbox, radio button, ecc.). page 1 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ <html xmlns=" http://www.w3.org/1999/xhtml"> <head> <title>Programmer Questionnaire</title> </head> <body> <form method="post" action="Default.aspx"> <div> Enter your first name:&nbsp; <input type="text" name="FirstName" /> <br /> Enter your last name:&nbsp; <input type="text" name="LastName" /> <br /><br /> You program with:<br /> &nbsp;&nbsp;&nbsp; <input type="checkbox" name="CS" />C# <br /> &nbsp;&nbsp;&nbsp; <input type="checkbox" name="VB" />VB .NET <br /> <br /> <input type="submit" value="Submit" id="OK" /> </div> </form> </body> </html> Quando l'utente fa clic sul pulsante di invio, il browser raccoglie il valore corrente di ogni controllo e lo incolla in una lunga stringa. Questa stringa viene inviata alla pagina indicata nel tag <form> (in questo caso, default.aspx) mediante un'operazione HTTP POST. In questo esempio il web server potrà ricevere una richiesta con la seguente stringa di informazioni: FirstName=Matthew&LastName=MacDonald&CS=on&VB=on Il browser segue alcune regole per la costruzione di questa stringa. Le informazioni sono sempre inviate come serie di coppie nome/valore separate da '&'. Ogni coppia nome/valore è diviso da un segno di uguale. Le caselle di controllo sono omesse a meno che esse siano 'segnate', nel qual caso viene passato il valore on. Per vedere page 2 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ come si usa il Form andare su http://www.w3.org/TR/REC-html40/interact/forms.html. Tutti i framework di programmazione server-side aggiungono un livello di astrazione sui dati grezzi del modulo. In ASP e ASP.NET, è possibile cercare i valori in base al nome della variabile nella collezione Request.Form. Ad esempio: string firstName = Request.Form["FirstName"]; Questa soluzione è però lontana da una soluzione Object Oriented. ASP.NET quindi aggiunge qualcosa di più, in modo da usare un approccio più Object Oriented. Infatti consente di utilizzare la seguente sintassi: string firstName = txtFirstName.Text; dove però txtFirstName è il Server Control o l'HTML Control (runat="server") destinato a mantenere il valore del first name. Questo codice ha anche il vantaggio di essere indipendente dai tipi. In altre parole, se si sta recuperando lo stato della casella di controllo, riceverai un valore booleano vero o falso, invece di una stringa con la parola on. In questo modo, gli sviluppatori sono isolati dalle stranezze della sintassi HTML. In ASP.NET tutti i controlli sono collocati all'interno di un tag <form> che deve essere unico (contrassegnato con il runat = "server" in modo di lavorare sul lato server). Interfaccia utente dinamica Vediamo la differenza con ASP classico. Supponiamo di voler aggiornare una parte di testo in una pagina in modo da riflettere alcune informazioni inserite dall'utente subito prima. In ASP classico, si deve trovare un posto comodo per inserire un blocco di script che scrivere il codice HTML grezzo. Ecco un frammento di codice ASP che utilizza questo tecnica per visualizzare un messaggio di benvenuto di colore rosso: string message = "<span style=\"color:Red\">Welcome " + FirstName + " " + page 3 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ LastName + "</span>"; Response.Write(message); Utilizzando ASP.NET il tutto risulta più ordinato: <asp:Label id="lblWelcome" runat="server" /> lblWelcome.Text = "Welcome " + FirstName + " " + LastName; lblWelcome.ForeColor = Color.Red; DI seguito i vantaggi dell'uso di ASP.NET rispetto ASP classico: - Il codice ASP.NET è molto più facile da scrivere e quindi da mantenere. - Il codice ASP.NET possiamo scriverlo dove vogliamo. Nell'esempio precedente con ASP classico, invece dovevamo preoccuparci di dove inserire il codice in modo da far apparire il testo nel posto giusto. In ASP classico infatti l'organizzazione dei contenuti dinamici sisultava molto più caotica. - Non dobbiamo preoccuparci della sintassi HTML. - Non dobbiamo preoccuparci del tipo di browser che dovrà fare il rendering della pagina. Il Modello ad eventi di ASP.NET Classic ASP utilizza un modello lineare di elaborazione. Questo significa che il codice della pagina deve essere scritto considerando il fatto che questo viene elaborato in ordine dall'inizio alla fine. ASP.NET è invece event-driven. Ogni gestore di eventi è un metodo, che mantiene il codice della pagina ordinato e ben organizzato. Di seguito un breve riassunto di come gli eventi funzionano in ASP.NET: page 4 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ 1. La pagina viene eseguita per la prima volta. ASP.NET crea la pagina ed i controlli, il codice di inizializzazione viene eseguito, successivamente la pagina viene rederizzata in formato HTML e restituita al client. Gli oggetti della pagina sono poi rilasciati dalla memoria del server. 2. Ad un certo punto, l'utente fa qualcosa che fa scattare un postback, come ad esempio clic su un pulsante. A questo punto, la pagina viene mandata al server con tutti i dati del modulo. 3. ASP.NET ntercetta la pagina restituita e ricrea gli oggetti della pagina, tenendo cura della possibilità di restituirli allo stato in cui erano l'ultima volta che la pagina era stata inviata. 4. ASP.NET controlla quale operazione ha fatto scattare il postback, e richiama il gestore eventi appropriato (come Button.Click). In genere, verranno eseguire alcune operazioni lato server (come ad esempio l'aggiornamento di un database o la lettura di dati da un file) e quindi modifica gli oggetti della pagina per visualizzare le nuove informazioni. 5. La pagina modificata viene renderizzata in HTML e restituita al client. La pagina e gli oggetti vengono rilasciati dalla memoria. Se si verifica un altro postback, ASP.NET ripete i passi da 2 a 5. Ricordiamo che ASP.NET supera il problema dell'assenza del mantenimento dello stato di HTML e quindi permette al programmatore di non preoccuparsi di ciò (grazie al ViewState). Postback automatici A differenza della gestione degli eventi in un programa Windows, in ASP.NET le azioni dell'utente avvengono lato client, mentre l'elaborazione avviene sul lato server. Ciò significa che è sempre necessaria una certa quantità di overhead in risposta a un evento. Per questo motivo, eventi rapidi (come ad esempio lo spostamento del mouse) sono completamente impraticabile nel mondo di ASP.NET. Per gestire eventi di quest tipo occorre utilizzare codice JavaScript lato client, o controlli AJAX (che comunque utilizzano JavaScript). L'esecuzione lato server, garantisce comunque un più alto livello di sicurezza. Con i moduli HTML, c'è un solo modo per fare il submit (invio al server) di una pagina: facendo clic su un pulsante submit. Se usiamo i controll server HTML nei nostri moduli web .aspx, questa è ancora l'unica opzione. Fortunatamente, i controlli ASP.NET web estendono questo modello con una funzione di postback automatico. Con questa funzione, i controlli di input possono generare eventi diversi, e il codice lato server sarà in grado di rispondere immediatamente. Ad page 5 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ esempio, è possibile attivare un postback quando l'utente fa clic su una casella di controllo, o modifica la selezione in un elenco, o modifica il testo in una casella di testo e poi si trasferisce a un altro campo. Questi eventi sono ancora a soluzione grosollana se paragonata agli gli eventi in un'applicazione Windows, ma sono un significativo passo in avanti dal semplice pulsante submit. Il postback automatico "sotto il cofano" Per usare il postback automatico, basta settare la porprietà AutoPostBack del Web Control a True (di default il valore è False). ASP.NET utilizza sul lato client le capacità di JavaScript per colmare il divario tra client-side e il codice lato server. Vediamo come funziona: se creiamo una pagina web al cui interno abbiamo controlli con AutoPostBack a True, ASP.NET aggiunge una funzione JavaScript alla pagina HTML denominata __doPostBack(). Quando viene chiamata, essa innesca un postback e rimanda indietro al server la pagina con tutte le informaizoni del form. ASP.NET aggiunge anche due campi di input nascosti che il __doPostBack() utilizza per passare le informazioni al server. Questa informazione è costituita dell'ID del controllo che ha scatenato l'evento ed eventuali altri informazioni rilevanti. Questi campi sono inizialmente vuoti: <div> <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> ... </div> La funzione __doPostBack() è responabile dell'impostazione in questi campi dei valori appropiati: <script type="text/javascript"> function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); ... } </script> } ASP.NET genera automaticamente la funzione __doPostBack(). Il suo codice sarà più lungo quanti più controlli con la proprietà AutoPostback=True aggiungiamo nella pagina. Quanlunque controllo con tale proprietà a True sarà collegato alla funzione attraverso gli attributi onclick o onchange. Questi attributi indicano a quali azioni il browser deve esguiere in risposta agli eventi client JavaScript onclik o onchange. In altre parole, ASP.NET passa da un evento lato client JavaScript ad un evento page 6 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ server-side utillizzanod il __doPostBack() come intermediario. Il postback automatico è disponibile solo con i Controlli Web. View State E' ll meccanismo con cui ASP.NET risolve il probela della natura stateless di HTTP. Ogni informazione sulla pagina viene persa ad ogni postback, quindi non posso tornare allo stato precedente della pagina. Tradizionalmente il problema veniva superato con l'uso dei cookies ed altri espedenti, ma tutte queste sono però soluzioni poco sicure. Il problema è il seguente: se io scrivo del testo su un campo e faccio submit, la pagina che mi ritorna in teoria dovrà avere il campo testo vuoto. Invece: come viene garantito, al recupero della pagina, che venga mantenuto il valore di tale campo ? Grazie al meccanismo del View State la pagina che ritorna al client potrà andare su questo "camp nascosto" per recuperare i valori dei controlli che avevano prima del submit. Per far fronte a tale problema, quindi, ASP.NET ha messo a punto un meccanismo integrato di serializzazione dello stato. In sostanza, una volta che il codice della pagina ha terminato l'esecuzione e poco prima che il codice HTML finale venga renderizzato ed inviato al client, ASP.NET esamina tutte le proprietà di tutti i controlli della pagina. Se una qualsiasi di queste proprietà è stata modificata dal suo stato iniziale, ASP.NET ne prende nota in una collezione nome/valore. Infine, ASP.NET prende tutte queste informazioni che ha accumulato e le serializza come una stringa Base64. La stringa finale viene inserita nella sezione <form> della pagina in un nuovo campo nascosto. La volta successiva che viene esguto il postback della pagina, ASP.NET segue i seguenti passaggi: 1. ASP.NET ricrea la pagina ed i suoi controlli basati sulle impostazioni page 7 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ predefinite (come definiti nel file .aspx). In questo modo la pagina ha lo stesso stato che aveva alla prima richiesta. 2. ASP.NET deserializza le informazioni del view state ed aggiorna tutti i controlli. Questa operazione riporta la pagina allo stato in cui era prima di essere inviata al cliente l'ultima volta. 3. Successivamente ASP.NET risistema la pagina in accordo ai dati inviati dal modulo. Per esempio se il client ha inserito del nuovo testo in una casella di testo, l'informazione sarà mantenuta nella collezione del Form ed ASP.NET lo userà per modificare i controlli corrispondenti. Dopo questo passo la pagina rifletterà lo stato corretto all'utente. 4. Ora il nostro codice di gestione degli eventi potrà essere invocato. ASP.NET innesca gli eventi appropriati ed il nostro codice potrà reagire ai cambiamenti della pagina, passare ad una nuova pagina o eseguire un'operazione cimpletamente diversa. La soluzione del View State aumenta la dimensione della pagina, in quanto il View State viene memorizzato al suo interno. Questo influenza il client doppiamente, perché il client non solo riceve una pagina più grande, ma deve anche inviare i dati del View State al server con ogni postback successivo, in questo modo ci vorrà più tempo sia per ricevere che per inviare la pagina. L'overhead si manifesta maggiormente quando nelal pagina abbiamo controlli complessi come una GridView. E' possibile disabilitare il View State impostando la proprietà EnableViewState su false. Tuttavia, in questo caso è necessario reinizializzare il controllo con ogni postback. Anche se si imposta EnableViewState su false, il controllo mantiene sempre alcune informazioni per il suo corretto funzionamento e questo viene chiamato Control State. Questo diventa interessante quando scriviamo controlli personalizzati. Il View State è utilizzato solo per le proprietà di pagine e controlli. ASP.NET non prevede lo stesso comportamento per variabili membro ed altri dati. Tuttavia è possibile inserire altri tipi di dati nel View State e recuperare queste informazioni manualmente in un secondo momento. E' essenziale ricordare che il modulo web è ricreato con ogni andata e ritorno. Questo rimane in memoria per il tempo necessario al rendering di una singola richiesta. page 8 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ Il View State "sotto il cofano" Consideriamo una semplice pagina ASP.NET con una label che memorizza la scritta "Hello Word" ed un bottone SUBMIT. Nella pagina renderizzata sarà facile individuare il nostro campo nascosto: <html> <head> <title>Hello World Page</title> </head> <body> <form method="post" action="Default3.aspx" id="form1"> <div class="aspNetHidden"> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/ wEPDwUKLTE2MjY5MTY1NQ9kFgICAw9kFgICAQ8PFgIe BFRleHQFDEhlbGxvIFdvcmxkIWRkZPsbiNOyNAufEt7OvNI bVYcGWH" /> ... </div> <div> <input type="submit" name="Button1" value="Button" id="Button1" /> <span id="lbl">Hello, world</span> </div> </form> </body> </html> E' possibile decodificare lato server, nel Page_Load con il codice seguente (è stata aggiunta una Label2 per visualizzare il contenuto decodificato): if (IsPostBack==true) { string viewStateString = Request["__VIEWSTATE"]; // viewStateString contains the view state information. // Convert the Base64 string to an ordinary array of bytes // representing ASCII characters byte[] stringBytes = Convert.FromBase64String(viewStateString); // Deserialize and display the string. string decodedViewState = System.Text.Encoding.ASCII.GetString(stringBytes); Label2.Text = decodedViewState; } Il testo decodificato avrà qualcosa di simile alla seguente stringa: page 9 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ ? -162691655dd-Text Hello, worldddd????4 ?????U?Xz? Come si può notare il testo risulta leggibile, quindi il View State non è il luogo per inserire informazioni sensibili; inoltre non fare affidamento sul contenuto del View State nelle nostre elaborazioni: non prendere decisioni in base al suo contenuto. Per rendere più sicure le nostre applicazioni è però possibile crittografare il View State in modo da non poter essere decodificato, oppure usare una funzione hash automatica. page 10 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ I blocchi del View State Alcuni server proxy, firewalls e browser mobili rifiutano campi nascosti più grandi di una certa dimensione. Per evitare questo problema ASP.NET divide in blocchi il View State. L'attributo maxPageStateFieldLength del tag <pages> del web.config, specifica la dimensione massima del View State, in byte: page 11 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ <configuration> <system.web> <pages maxPageStateFieldLength="1024" /> ... </system.web> </configuration> Quando la pagina richiede un View State più grande, ASP.NET lo divide in blocchi come nel seguente codice (anche se è molto raro che succeda): <input type="hidden" name="__VIEWSTATEFIELDCOUNT" value="3" /> <input type="hidden" name="__VIEWSTATE" value="..." /> <input type="hidden" name="__VIEWSTATE1" value="..." /> <input type="hidden" name="__VIEWSTATE2" value="..." /> Conformità XHTML Anche se i controlli ASP.NET sono conformi allo standard XHTML, tocca a noi rendere la nostra pagina nel complesso renderizzata in formato XHTML. XNTML non aggiunge funzionalità all'HTML 4.01, ma ha una sintassi più rigorosa. Questa contribuisce ad individuare piccoli errori, inoltre le pagine conformi risultano più semplici alle applicazioni da leggere o analizzare. Per le specifiche andare su http://www.w3.org/TR/xhtml11. Tutti i controlli ASP.NET rispettono lo standard, in particolare: - I nomi delle variabili e degli attributi sono in minuscolo. - Tutti gli elementi devono essere chiusi, o devono utilizzare un unico tag che si chiude(<br />). - Tutti i valori degli attributi devono essere racchiusi tra virgolette singole o doppie - L'attributo id deve essere usato al posto dell'attributo name. page 12 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ XHTML rimuove anche il supporto ad alcune caratteristiche ammesse in HTML come i frame e la formattazione senza CSS. Una caratteristica non presente in XHTML, ma comunque molto usata è l'attributo target . I seguenti controlli ASP.NET lo ammettono: AdRotator, TreeNode, HyperLink, HyperLinkColumn, BulletedList. Utilizzare l'attributo target rende la pagina non più conforme allo standard XHTML. Tale attributo comunque non causerà nessun problema di browser moderni. Tuttavia, se è necessario creare un sito web che deve essere completamente compatibile con XHTML, è necessario evitare di utilizzare l'attributo target. Nell'immediato non si intuisce il vantaggio dell'uso di XHTML, ma questo garantisce la compatibilità con le evoluzioni future dello standard. Sarà facilmente estendibile con nuove funzionalità di markup come XSLT, inoltre il documento XHTML può essere trasformato in altre forme basate su XML Document Type Definitions (DTD) Ogni documento XHTML deve iniziare con un doctype (Document Type Definition), che definisce il tipo di XHTML che utilizza. In una pagina ASP.NET, il doctype deve essere posto immediatamente dopo la direttiva di pagina. In questo modo, il doctype sarà renderizzato come prima riga del documento (è un requisito): <%@ Page Language="C#" AutoEventWireup="true" CodeFile="TestPage.aspx.cs" Inherits="TestPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > ... Questa pagina definisce anche lo spazio dei nomi XML per l'elemento <html>. Se non si vuole sostenere lo standard XHTML 1.1, si può fare un compromesso. Una possibilità è la scelta di XHTML 1.0 Transitional per il doctype, che in pratica applica le regole strutturali di XHTML ma permette funzionalità di formattazione HTML che nello standard 1.1 sono stati sostituiti dai CSS. Ecco il tipo di documento è necessario: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> Se abbiamo bisogno anche dei frame ma vogliamo rimanere con lo standard XHTML possiam usare il seguente DTD page 13 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> I controlli ASP.NET funzionano con qualunque doctype. Sta a noi scegliere il livello di standard da seguire. E' essenziale comunque inserire il DTD in quanto senza di questo ogni browser potrebbe avere un comportamento differente. Configurare il rendering XHTML I controlli server ASP.NET usano automaticamente lo standard XHTML 1.0 strict. Il rendering XHTML viene impostato tramite un attributo di file di configurazione chiamato controlRenderingCompatibilityVersion, che viene applicato sulla <pages>. Per impostazione predefinita, attributo è impostato nel web.config principale, in modo che si applica a tutte le applicazioni ASP.NET 4.0: <configuration> <system.web> <pages controlRenderingCompatibilityVersion="4.0" /> </configuration> ... </system.web> Impostando un valore diverso si impone la compatibilità con le versioni più vecchie di ASP.NET, ad esempio 3.5. Per ottenere le restrizioni più severe, eliminare tale attributo. Se si vuole usare la versione 3.5 è possibile utilizzare un altra impostazione sul web.config, <xhtmlConformance> che ha come attributo la voce more che può assumere i seguenti valori - Strict: ottiene un XHTML quasi pulito come quello che si ottiene con controlRenderingCompatibilityVersion="4.0" - Transitional: valore predefinito. Produce un rendering compatibile con XHTML, ma un piccolo gruppo di stranezze vietate dal rendering XHTML Strict (attributo name per <form>, border=0 per alcuni controlli). - Legacy: porta il rendering alla versione ASP.NET 1.1 Nota: Le incoerenze di rendering in ASP.NET 3.5 non comportano errori. I browser saranno sempre in grado di elaborare la pagina con successo, anche se si utilizza il doctype XHTML 1.1 rigoroso. Tuttavia, le incongruenze saranno segnalate come errore da uno strumento di validazione XHTML. page 14 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ Default doctype per Visual Studio Quando si screa una nuova web form, Visual Studio aggiunge automaticamente un doctype per l'XHTML Transitional. Se non si vuole questo, occorre modificare il doctype in ogni pagina. Se stiamo utilizzando una master page, basta impostare qui il doctype in modo che tutte le pagine figlio che la utilizzeranno lo acquisiranno automaticamente E' possibile ambiare il template della web page di Visual Studio, in modo da utilizzare doctype differenti, ma il procedimento è un po' tortuso. E' necessario prima modificare i template e poi fare il rebuild della cache dei template di Visual Studio. Di seguito i passi da seguire: - È possibile trovare i template di Visual Studio in una serie di file ZIP in diverse cartelle. Nel nostro caso è necessario modificare i file WebForm.aspx e WebForm_cb.aspx in c: \ Program Files \ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ ItemTemplates \ Web \ CSharp \ 1033 \ WebForm.zip. Se siamo in una versione a 64 bit di Windows, al posto di c troveremo Program Files (x86). - copiare l'archivio su un'altra posizione, estrarre i file appropriati, modificarli, aggiungerli di nuovo all'archivio, e quindi copiare l'intero archivio nuovamente nella posizione originale. Questo perché è necessario disporre dei diritti di amministratore per modificare questi file. - Dopo aver aggiornato i template, eliminare la cartella C: \ Programmi \ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ ItemTemplatesCache per cancellare il template dalla cache. - Eseguire Visual Studio utilizzando la seguente riga di comando per ricostruire la cache dei modelli (questo passaggio richiede privilegi di amministratore): devenv / InstallVSTemplates - È ora possibile eseguire Visual Studio normalmente. Tutti i nuovi template web aggiunti a una applicazione web dovrebbe avere il doctype nuovo che abbiamo impostato. Validazione XHTML Per assicurarsi che l'intera pagina sia XHTML-Compilant è necessario assicurarsi che qualunque contenuto statico che si aggiunge rispetti le regole XHTML. Vusual Studio ci corre in aiuto con un validatore built-in : attivare il menu Modifica Origine HTML e nell'elenco a discesa Schema di destinazione per la convalida selezionare il page 15 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ tipo di validazione da applicare. Tutti i tag non conformi verranno così evidenziati, come ad esempio il tag <br> in una validazione XHTML 1.1. Rimane però il problema dei controlli di terze parti: come si fa ad assicurarsi che il rendering di tali controlli sia l'XHTML-Compilant ? Occorre un validatore di terze parti. Una buona risorsa è il servizio gratuito di validazione W3C in http://validator.w3.org. Ricordiamo che questo deve essere fatto sulla pagina finale, quindi sull'URL o sul file aspx renderizzato (cioè sul codice presente nel browser). ID lato client dei controlli ASP.NET richiede che gli elementi lato client abbiano un ID univoco. Ma perché non usare gli stessi ID lato server ? In primo luogo, un controllo lato server può esistere senza server ID. In secondo luogo, un singolo controllo può occorrere più volte nella pagina in diversi container (come gli oggetti di una riga di una GridView che sono ripetuti per ogni nuova riga). Per far fronte a scenari come questi, ASP.NET fonde insieme all'ID del controllo server con tutti i suoi naming container, e (se si tratta di dati associati) anche con un indice numerico. Questo porta a lunghi e scomodi client ID, come il seguente : ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel_TextBox1 Un Naming Container è un controllo che implementa l'interfaccia INamingContainer. I Naming Container includono l'oggetto Page, gli User Control, i Content e tutti i controlli che possono essere associati ad un elenco di dati (dai più semplici HtmlSelect, ListBox, e CheckBoxList ai più ricchi come Details, FormView e GridView). Tuttavia non tutti i contenitori sono Naming Container, come ad esempio Panel che semplicemente avvolge l'elemento <div>. Il client ID può servire per fare riferimento ad un oggetto in un CSS oppure per fare manipolazioni con JavaScript, ma utilizzare quello generato di default risulta piuttosto complesso. A questo proposito ASP.NET 4.0 aggiunge la proprietà ClientIDMode che consente di modificare il sistema di denominazione di una intera pagina, di una sezione di una pagina, o un singolo controllo. Tale proprietà è un membro della classe di base Control da cui tutti i controlli Web ASP.NET derivano. Esso supporta quattro possibili valori: - AutoID: il client ID è generato concatenando gli ID del controllo con gli ID dei page 16 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ Naming Container, separati da un carattere di sottolineatura. Viene aggiunto un indice numerico se il controllo viene associato a un controllo dati. Per esempio: ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel_TextBox1. - Static: Utilizza lo stesso server ID per impostare il client ID. Questo è da usare in casi semplice. Infatti si può incorrere in problemi se il controllo viene ripetuto nella pagina in differenti Naming Container. Per esempio: TextBox1. - Predictable: viene usato lo stesso metodo dell'AutoID, ma non include l'ID della pagina di livello superiore (come ctl00) ed inoltre viene usata la proprietà ClientIDRowSuffix per generare valori univoci in un controllo associato ai dati (che ha più senso di un indice numerico standard). Per esempio: ContentPlaceHolder1_ParentPanel_NamingPanel_TextBox1. - Inherit: viene usata la strategia di denominazione del Naming Container padre. O, se questo è impostato nella pagina, utilizza la strategia di denominazione che è specificato nel tag <pages> del file web.config. L'impostazione predefinita di ClientIDMode è Inherit per ogni controllo. Ciò significa che il controllo prende il ClientIDMode del suo Naming Container padre. Questa eredità si propaga fino alla pagina di livello superiore, che eredita l'impostazione ClientIDMode dal <pages> del file web.config. In una nuovo sito ASP.NET 4, nel web.config principale viene impostato ClientIDMode=Predictable. ma in un sito web che è stata eseguita la migrazione ad ASP.NET 4 da una versione precedente di ASP.NET, Visual Studio imposta ClientIDMode=AutoID per la compatibilità. <configuration> <system.web> </system.web> </configuration> <pages clientIDMode="AutoID" /> ... Naturalmente è possibile rimuovere o modificare la proprietà ClientIDMode in base alle esigenze. Come scegliere la modalità giusta: - Se non è necessario fare riferimento a elementi lato client, non occorre pensare questo problema. page 17 / 18 Solo quello che ti interessa | WEB FORM - Page processing Copyright admin [email protected] http://www.belloma.it/web-form-page-processing/ - Se occorre fare riferimento ad un elemento lato client, il modo più semplice per farlo è impostare il valore Static. - Se si utilizzano spesso i controlli sul lato client che contengono controlli associati adi dati o elementi ripetuti è possibile impostare per questi controlli il valore Predictable (insieme alla proprietà ClientIDRowSuffix). page 18 / 18