Condividi tramite


Gli standard web al servizio ASP.NET 2.0

di Daniele Bochicchio- Microsoft MVP

Obbligare ASP.NET 1.1 a essere più vicino agli standard web è stato per diversi anni una pratica per certi versi divertente, perché obbligava ad utilizzare molti trucchi e molto olio di gomito durante la creazione delle applicazioni.

In oltre 3 anni di sviluppo, ASP.NET 2.0 ha potuto trarre il meglio da quelli che sono gli standard web, anche perché i tempi in cui è stato progettato e poi sviluppato sono decisamente differenti rispetto al passato. In questo periodo, infatti, gli standard web sono tornati ad avere il loro giusto peso e l’importanza che si meritano, così che oggi ASP.NET 2.0 è completamente in grado di abbracciarli ed anzi ne consente la diffusione in maniera davvero semplice, a patto di conoscere alcune funzionalità appena aggiunte.

In questa pagina

Cosa vuol dire usare gli standard web Cosa vuol dire usare gli standard web
Breve introduzione ad XHTML e CSS Breve introduzione ad XHTML e CSS
Un esempio di layout tableless Un esempio di layout tableless
Per il markup meglio usare XHTML 1.1 Per il markup meglio usare XHTML 1.1
Il supporto di ASP.NET 2.0 ad XHTML Il supporto di ASP.NET 2.0 ad XHTML
Adaptive Rendering: come i controlli cambiano output Adaptive Rendering: come i controlli cambiano output
Validare le pagine con il Validatore del W3C Validare le pagine con il Validatore del W3C
Alcuni controlli da evitare per XHTML 1.1 Alcuni controlli da evitare per XHTML 1.1
I CSS Control Adapters I CSS Control Adapters
Conclusioni Conclusioni
Approfondimenti Approfondimenti

Cosa vuol dire usare gli standard web

Uno standard è per definizione qualcosa su cui una serie di entità si mettono d’accordo, formalizzando le regole alla base di un certo processo. Nel caso del web, gli standard web sono gestiti da un organismo che si chiama W3C (World Wide Web Consortium), che ha il compito di coordinare diversi vendor, governi ed associazioni no profit, con il fine ultimo di regolare la creazione e diffusione di standard condivisi applicabili al web.

Nel mondo del web, avere standard vuol dire poter creare applicazioni che poi diversi tipi di device saranno in grado di supportare. Tendenzialmente noi siamo abituati ad associare il concetto di device a quello di browser e quindi a ridurre il tutto al duopolio Internet Explorer – Mozilla. In realtà esiste una miriade di altri browser, pensati per situazioni ed utenti differenti.

L’idea alla base degli standard web è infatti quella di garantire la costruzione di un ecosistema più rispettoso di quelle che sono le diverse caratteristiche che i device utilizzati dagli utenti (e quindi gli utenti stessi) possono comportare. Oggi non facciamo fatica a capire che un browser può anche essere su un terminale con poche risorse, come un cellulare o un Pocket PC, così come ci possono essere più sistemi operativi, rispetto a Windows. È il bello del web, senza dubbio, dove le applicazioni possono essere pensate in maniera tale che l’interfaccia grafica sia visibile su qualsiasi piattaforma.

Quello che spesso dimentichiamo, però, è che ci sono tanti browser e non tutti sono visuali, come quelli a cui siamo abituati. C’è tutto un gruppo di utenti diversamente abili, che utilizza versioni specifiche, in grado di supportare al meglio non vedenti, ipovedenti o persone con qualsiasi altra difficoltà.

Come normodotati tendiamo a dimenticare di frequente che una pagina web è prima di tutto un documento, cioè un contenitore di informazioni. Ci concentriamo maggiormente su quelle che sono le caratteristiche grafiche, tralasciando il fatto che ci può essere un utente che invece ha interesse a leggerne “solo” le informazioni, perché ad esempio utilizza un browser vocale o braille.

L’utilizzo degli standard web consente appunto la creazione di applicazioni più rispettose di tutti, perché gli standard web non servono per riempire tonnellate di pagine di documentazione, ma a fare in modo che i diversi produttori di browser, prima, e gli sviluppatori, poi, possano lavorare su una serie di specifiche comuni, così che il risultato possa essere interpretato al meglio dai diversi browser attualmente disponibili.

L’obiettivo che si vuole raggiungere, in questi casi, è quello di garantire maggiore accessibilità alle informazioni.

 

Breve introduzione ad XHTML e CSS

Quello che tutti, come sviluppatori web, abbiamo fatto negli ultimi anni è creare applicazioni web male e per giunta in maniera obsoleta.

L’utilizzo delle tabelle come sistema per identificare la struttura di un sito è infatti una pratica fortemente sbagliata, perché le tabelle sono nate per contenere dati di tipo statistico, piuttosto che elenchi, ma non di certo per rappresentare una struttura, quale è quella della pagina.

Ci sono tecnologie specifiche per fare in modo che la pagina torni ad essere un documento, proprio come era nell’idea iniziale di chi ha definito le prime specifiche HTML, senza però trascurare l’impatto grafico, che con la commercializzazione di Internet è inevitabile ed anzi utile, ben sapendo però che è necessario dare il supporto anche a chi di questa interfaccia non vedrà mai niente, ma è interessato solo alle informazioni che contiene.

Riportando dunque il tutto ad un discorso più vicino alle raccomandazioni, il linguaggio per definire l’aspetto grafico rispetto alla struttura cambia e viene salvato, come è giusto che sia, all’interno del documento CSS (Cascading Style Sheets), chiamato spesso foglio di stile.

L’idea alla base dei layout tableless è, infatti, quella di rendere possibile una facile separazione tra markup, che continua ad essere definito con HTML 4.01 o XHTML 1.1 (o nelle versioni 1.0), e parte visuale, che viene appunto demandata al CSS.

Il documento, a questo punto, smette di avere una qualsiasi forma di layout, conservando soltanto la struttura, che poi attraverso il CSS sarà adattata per avere un aspetto grafico tipico di un sito web.

 

Un esempio di layout tableless

Uno dei motivi per cui molti sviluppatori non usano questa tipologia di approccio nella definizione delle pagine web è che pensano che sia meno potente dello sviluppo basato su tabelle, mentre invece è esattamente il contrario.

Se prendiamo un tipico layout a tre colonne, l’utilizzo dei CSS consente di definire in un solo punto il comportamento del layout, garantendo al contempo che sia possibile implementare esattamente le stesse identiche caratteristiche di un layout basato su tabelle, ma separando nettamente i due ambiti. E con il vantaggio che si può applicare un CSS per la stampa allo stesso markup, nascondendo elementi e dando dunque un significato davvero diverso ai contenuti.

Nell’esempio che segue è definito il markup, con la sola struttura per un layout a due colonne, che non si discosta molto dal caso in cui ne siano presenti tre:

<!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 runat="server">
    <title>Layout tabless</title>
    <link href="Style.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">

    <div id="header">
    <h1>Il mio sito</h1>
    </div>
    
   
    <div id="body">
    
        <div id="left">
           Parte di sinistra<br />
        </div>
        <div id="center">
        <p>Contenuto della pagina.</p>
        </div>

    </div>
    
    </form>
</body>
</html>

Il file style.css viene caricato e da’ alla pagina l’aspetto finale, in cui si può notare che la colonna di destra è grigia ed è separata, rispetto al resto del contenuto vero e proprio, sfruttando questa definizione:

#body
{
clear:both;
}

#left
{
float:left;
width: 210px;
background-color: #c0c0c0;
}

#center
{
float:right;
width: 600px;
}


Figura 1–Un tipico layout tableless a due colonne

L’effetto che si ottiene con i CSS è del tutto simile all’analogo approccio basato sulle tabelle, però basta provare i due layout, semplici, con un browser vocale per capire quanto questo impatti sulle persone che ne fanno uso. E poi, un layout basato su CSS favorisce anche l’implementazione di soluzioni che possano cambiare il layout grafico agendo solo sul foglio di stile, come evidenziato dall’ottimo CssZenGarden. In questo particolare caso, infatti, viene offerta una struttura di markup fissa, su cui i visitatori possono applicare, dopo upload, un proprio CSS. Se si da un’occhiata alla gallery, si può notare che a fronte di un solo codice, si possono avere effetti anche diametralmente opposti, grazie alla netta separazione tra struttura e rappresentazione grafica della stessa.

 

Per il markup meglio usare XHTML 1.1

Non c’è niente di male nell’usare HTML 4.01, se non che ovviamente XHTML nella sua versione 1.1 rappresenta l’ultima incarnazione di XHTML, che è disponibile anche nelle versioni 1.0 Transitional, per chi arriva da HTML 4.01, e Strict, che di fatto è come XHTML 1.1, che ha solo qualche attributo in meno su alcuni tag, come quello target sui link.

XHTML rispetto ad HTML consente di utilizzare un linguaggio XML based, con tutti i vantaggi che l’utilizzo di un markup più rigoroso comporta per il browser, che può cercare di ovviare il meno possibile alle dimenticanze dello sviluppatore.

Le regole di XHTML sono quelle di XML e prevedono che il documento sia valido e well formed, con l’utilizzo sempre di un tag di chiusura, un corretto annidamento dei tag stessi e l’inclusione dei valori delle proprietà tra virgolette.

Il vero vantaggio di XHTML è che resta di fondo un linguaggio basato su XML, attraverso uno schema specifico, dunque può esser facilmente generato a partire da altri formati, piuttosto che trasformato utilizzando XSL-T. E che in fin dei conti marca in maniera ben più netta il fatto che il markup serve solo per la struttura, laddove invece i CSS sono il mezzo attraverso cui bisogna dare a questa struttura un layout.

 

Il supporto di ASP.NET 2.0 ad XHTML

La versione 1.1 di ASP.NET, in tutta franchezza, è tutto tranne che pronta per XHTML ed i motivi sono storici: è uscita in un periodo in cui di XHTML si cominciava a parlare ma quasi nessuno, nè tanto meno i browser, erano in grado di offrire un vero supporto che non fosse quello derivante dal fatto che HTML 4.01 e XHTML hanno diversi punti di contatto che li rendono simili agli occhi di un browser.

La versione 2.0 invece risponde in maniera migliore a questa necessità, poiché il rilascio è avvenuto nel 2005, avendo come obiettivo dichiarato quello di essere in grado di supportare il maggior numero possibile di browser e piattaforme.

Gran parte dei controlli disponibili insieme ad ASP.NET 2.0 emettono codice XHTML 1.0 Transitional, anche se è possibile fargli utilizzare anche la versione Strict, con una piccola modifica.

Il motivo per cui questi controlli non emettono, già di default, XHTML 1.0 Strict è da ricercarsi nella differenza più marcata che queste due varianti comportano: con Transitional c’è il supporto per l’attributo name nei tag, che invece Stict non ha. Questo cambiamento porta a dover ripensare il codice Javascript scritto solo per Internet Explorer, che anziché utilizzare il DOM (Document Object Model), attraverso document.getElementById(), fa uso direttamente dell’oggetto, con document.nomeOggetto. Considerando che VS.NET 2003 è in grado di supportare l’intellisense solo per questa variante proprietaria di IE, la scelta è stata quella di rendere meno traumatico possibile il cambio di versioni nel caso di progetti web già esistenti e che ne facessero erroneamente uso.

Se si utilizza già il DOM, praticamente il passaggio ad XHTML 1.0 Strict (o 1.1, direttamente) è indolore, ma necessita dell’aggiunta di un tag specifico al web.config:

<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<xhtmlConformance mode="Strict"/>
</system.web>
</configuration>

Se si da’ uno sguardo al markup, con l’impostazione sul valore di default (Transitional) si può notare questo output:

<form name="form1" method="post" action="default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
value="/wEPDwULLTE0MDkxNzYwNDNkZNj0aqjq1bt2Cqc27JzUSVlpjYHW" />
…

Variando invece il web.config, giustamente nel tag form viene omesso l’attributo name, come da specifiche, con questo codice come risultato:

<form method="post" action="default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" 
value="/wEPDwULLTE0MDkxNzYwNDNkZNj0aqjq1bt2Cqc27JzUSVlpjYHW" />
…

L’effetto visivo è praticamente lo stesso, ma il codice emesso è differente, con la seconda versione che fa un uso migliore di XHTML.

Tutti i controlli inclusi in ASP.NET 2.0 utilizzano questa impostazione del web.config per decidere quale tipo di markup emettere, anche se molti sono ancora basati su tabelle, poichè XHTML, infatti, ne include giustamente il supporto, ma per poter creare liste ordinate di informazioni, non per impaginare il layout.

Il motivo per cui i controlli non implementino già di default layout privi di tabelle è da ricercare, probabilmente, nel poco tempo a disposizione per il rilascio della versione 2.0 e nella necessità, comunque, di garantire la maggior compatibilità possibile con il passato.

 

Adaptive Rendering: come i controlli cambiano output

ASP.NET fin delle prime versioni sfrutta un meccanismo noto come Adaptive Rendering per adattare il proprio output in base al device che richiede la pagina, usando lo user agent inviato dai browser ed una serie di file di definizione per capire quali caratteristiche possano essere sfruttate da quest’ultimo.

Nelle versioni 1.x la funzionalità è soltanto abbozzata, ma si può vedere all’opera già dando un’occhiata ai Validator Controls, che non riconosco correttamente FireFox e non generano, se si utilizza questo browser, la parte client-side relativa alla validazione.

Con ASP.NET 2.0 fortunatamente i file di definizione sono stati aggiornati, insieme al codice Javascript che nella versione 1.1 è solo per IE, così che ora possono essere sfruttati al meglio anche per generare l’output associato ai singoli controlli.

In realtà l’intera infrastruttura dei server control è stata rivista, così che l’intero meccanismo di generazione dell’output è in pratica del tutto slegato dal controllo stesso e demandato ad una classe esterna, specificata attraverso un file particolare, che ha estensione .browser e si trova nel percorso %windir%\Microsoft.NET\Framework\ v2.0.50727\CONFIG\Browsers\.

In questo modo è possibile cambiare anche nella singola applicazione locale, utilizzando la nuova directory /App_Browsers/, l’output associato ai controlli presenti con ASP.NET 2.0, per adattarli a scenari particolari, o più semplicemente per fare in modo che utilizzino sempre e comunque un layout table-less anzichè uno basato su tabelle.

 

Validare le pagine con il Validatore del W3C

Se provate a creare una pagina e la fate validare al Validatore del W3C, noterete che vi darà alcuni warning relativi al fatto che in realtà non è stato emesso codice XHTML. ASP.NET non riconosce il browser e fa la scelta conservativa di servire HTML, così da esser certo di inviare qualcosa che la maggior parte dei browser siano in grado interpretare.

Se si vuole invece che un certo browser riceva XHTML, è necessario creare un nuovo file di nome w3c.browser in /App_Browsers/ o nella già citata %windir%\Microsoft.NET\Framework\ v2.0.50727\CONFIG\Browsers\, per tutte le applicazioni, così che diventi un browser riconosciuto. Segue quello da aggiungere per il browser del Validatore del W3C:

<browsers>
<browser id="W3C_Validator" parentID="default">
<identification>
<userAgent match="^W3C_Validator" />
</identification>
<capabilities>
<capability name="browser" value="W3C Validator" />
<capability name="ecmaScriptVersion" value="1.2" />
<capability name="javascript" value="true" />
<capability name="supportsCss" value="true" />
<capability name="tables" value="true" />
<capability name="w3cdomversion" value="1.0" />
<capability name="tagWriter" value="System.Web.UI.HtmlTextWriter" />
</capabilities>
</browser>
</browsers>

La chiave di tutto è proprio la riga che imposta il tagWriter, cioè quella classe particolare che si occupa di generare l’output per il controllo, provvedendo alla creazione dell’output finale.

Attraverso questo meccanismo è possibile forzare qualsiasi browser a ricevere un output nel formato desiderato, che può anche essere diverso da HTML o XHTML, come nel caso dei mobile controls, che sono in grado di generare output nei diversi formati supportati dai mobile device, come WML (WAP) o cHTML (i-mode), utilizzando sempre però sempre lo stesso tipo di control, senza modifiche necessarie alla pagina ASP.NET.

 

Alcuni controlli da evitare per XHTML 1.1

Se il vostro obiettivo, magari perché dovete sottostare a leggi particolari che vi obbligano ad usare standard web, è quello di avere XHTML 1.1, sappiate che alcuni controlli sono ancora basati su tabelle ed altri invece vanno usati entro certi limiti. Se nel primo caso il problema è relativo all’accessibilità e non al markup vero e proprio, nel secondo è esattamente il contrario.

Per compatibilità, i seguenti controlli hanno un attributo che genera a propria volta un attributo target sul markup associato ai link, che non è incluso in XHTML 1.1:

  • AdRotator

  • BulletedList

  • HyperLink

  • HyperLinkColumn

  • ImageMap

  • MenuItem

  • TreeNode

Per fare in modo che emettano XHTML 1.1 valido, basta non usare questo attributo. Se si vuole invece emulare il comportamento con Javascript, bisogna passare l’URL ad una funzione, che al click poi richiami un normale Javascript che faccia uso di window.open:

<a href="http://www.aspitalia.com" onClick="blankPage(this); return false;">ASPItalia.com</a>
<script type="text/javascript"><!-- 
function blankPage(url) {window.open(url);} 
//--></script>

L’effetto che si ottiene è praticamente identico all’utilizzo dell’attributo target, ma in caso di browser che non supportino Javascript o l’interfaccia a più finestre, l’effetto è quello di riutilizzare quella corrente.

 

I CSS Control Adapters

Proprio per via dell’architettura estendibile, che rende possibile il cambio dell’output senza toccare le definizioni dei controlli, Microsoft ha rilasciato nel mese di novembre 2005 un ToolKit che contiene alcune classi che cambiano l’output associato ad alcuni controlli ancora basati su tabelle, rendendo possibile l’uso di classi che generano layout tableless.

Il bello dei CSS Controls Adapters, che si scaricano gratuitamente, è che agiscono sulle applicazioni già esistenti, senza necessità che queste vengano toccate, perché la registrazione degli adapters viene fatta, come già detto, all’interno di un file .browser. Gli adapter forniti da Microsoft agiscono sui controlli TreeView, Menu, GridView, DetailsView, FormView e di Login (Login, CreateUserWizard, etc)

Il meccanismo che carica gli adapter (che possono essere applicati a tutti i web control, anche partendo da quelli inclusi nel ToolKit) è davvero semplice e qui schematizzato:

  • viene invocato il metodo Control.ResolveAdapter;

  • viene richiamato l’adapter giusto per generare l’output, riportando poi il flusso nel controllo stesso. Se si restituisce null, si può bloccare il meccanismo in custom control di propria creazione.

Un Control Adapter, che è una classe a tutti gli effetti, può supportare ViewState, PostBack e DataBinding, dunque in teoria qualsiasi controllo può avere un proprio adapter e non rinunciare a nessuna delle funzionalità già previste dal controllo.

Generalmente un adapter sovrascrive il metodo Render della classe base ControlAdapter, da cui deve derivare, per fornire un proprio risultato personalizzato. Volendo è possibile controllare anche l’output della pagina, attraverso l’utilizzo di un PageAdapter, mentre per lavorare direttamente con i Web Controls, si può utilizzare la classe WebControlAdapter anzichè la generica ControlAdapter.


Figura 2 - Il risultato di un adapter applicato ad un controllo TextBox

Di seguito l’esempio di un adapter applicato al controllo TextBox, che ne cambia l’output aggiungendo un link prima del controllo stesso:

using System.Web;
using System.Web.UI;
using System.Web.UI.Adapters;
using System.Web.UI.WebControls;

namespace ASPItalia.com.Adapters
{
public class TextBoxAdapter : ControlAdapter
{
// Cambio il rendering
protected override void Render(HtmlTextWriter writer)
{
// render personalizzato
HyperLink a = new HyperLink();
a.Text = "Popup ";
a.NavigateUrl = "#";
a.RenderControl(writer);

// render del controllo di base
base.Render(writer);
}

}

}

È sufficiente dare un’occhiata al markup generato dai controlli a cui viene applicato l’adapter per rendersi conto di quanto questo abbia effetto anche in maniera profonda sulla qualità del codice generato.

 

Conclusioni

ASP.NET 2.0 ha fatto passi da gigante, anche grazie a VS 2005, nella direzione di un miglior supporto per gli standard nelle applicazioni web. Il solo fatto che i controlli siano in grado di generare un output migliore consente di utilizzare questa tecnologia in tutti quei progetti in cui l’accessibilità a quante più persone possibili, con caratteristiche differenti, è una necessità.

L’Adaptive Rendering, poi, è davvero la ciliegina sulla torta, perchè consente di cambiare a posteriori l’output prodotto da qualsiasi controllo, senza necessità di intervenire nel markup, ma agendo direttamente attraverso dei semplici file di configurazioni abbinati a classi.

 

Approfondimenti