Uno dei temi caldi che uno sviluppatore web deve “sempre” affrontare, è sicuramente la “browser compatibility”, ovvero rendere il sito accessibile e di stesso aspetto (per quanto possibile) indipendentemente dal browser utilizzato.
Costruire un sito Cross-Browser, ovvero un sito che abbia la capacità di supportare tutti i browser, implica un lavoro non indifferente sia per chi svolge il ruolo di sviluppatore, sia per chi svolge il ruolo di grafico.
A partire dagli anni 90, quando iniziò la “guerra dei browser”, e fino a questi ultimi anni, quando la concorrenza tra diversi browser si è ancor di più allargata, si sono sviluppate molteplici tecniche per arrivare allo stesso risultato.
In questo articolo voglio presentare come Microsoft ha affrontato questo problema, mettendo a disposizione diversi strumenti, classi e “feature” per .

Quali sono le cause di una diversa visualizzazione del sito?

  1. Browser differenti (IE, FF, chrome, ecc.)
  2. Versioni del browser differenti (IE5, IE6, IE7, ecc.)
  3. Computer/Device differenti (PC, MAC, SmartPhone, ecc)
  4. Comportamenti differenti (browser’s bugs, errori HTML, javascript, ecc.)

Quello che solitamente facciamo, sia nei file css, sia nel codice javascript, sia nel codice HTML, è riconoscere il tipo di browser, la versione, e scrivere il codice di conseguenza. Ad esempio possiamo modificare gli stili in questa maniera:

<!--[if lte IE 7]>
<link rel='stylesheet' id='ie-css'  href='IE7_style.css' type='text/css' media='all' />
<![endif]-->

oppure utilizzare un framework javascript (es. JQuery) capace di automatizzare queste operazioni ( e ) per modificare lato client l’aspetto della pagina.

Usando queste tecniche, stiamo agendo prevalentemente lato client; ciò implica dover scrivere più codice (CSS, JavaScript, HTML) e soprattutto doverlo inviare al browser con un conseguente aumento dei dati che viaggiano sulla rete.
Ideale sarebbe poter agire a monte, ovvero sul server, e agire di conseguenza inviando solo ciò che è necessario per il browser specifico.

La classe System.Web.HttpBrowserCapabilities

ASP.NET mette a disposizione fin dalla prima versione, la classe che fornisce informazioni riguardo il browser o il dispositivo client che sta effettuando la richiesta HTTP (non tutte le informazioni).
L’oggetto espone una serie di proprietà fortemente tipizzate e quindi facilmente utilizzabili. Esempio:

System.Web.HttpBrowserCapabilities browserClient = Request.Browser;
bool isCellular = browserClient.IsMobileDevice;

Questo oggetto non è altro che un “mapping” di alcune delle proprietà di un browser. La configurazione di un browser viene memorizzata nei file di definizione .browser che ASP.NET mette a disposizione.
Questi file si trovano nella cartella
%SystemRoot%\Microsoft.NET\Framework\versionNumber\Config\Browsers

Non voglio entrare nel merito di questi file, dico soltanto che oltre al set di file già fornito, è possibile sia personalizzare che creare nuovi file per tipi di browser personalizzati.

Vediamo alcune di queste proprietà messe a disposizione dalla classe:

ActiveXControl Indica se il browser supporta i controlli ActiveX
Browser Indica la stringa del browser inviata come User-Agent
ClrVersion Indica la versione .NET installata sul client
Cookies Indica se il browser supporta i cookies
Crawler Indica se il browser è uno spider di un motore di ricerca
EcmaScriptVersion Indica la versione di EcmaScript supportata
Frames Indica se il browser supporta i frames
HasBackButton indica se il browser ha un pulsante Back dedicat

e molti altri ancora.

Forti di questi dati, possiamo ad esempio scegliere il file CSS da utilizzare, il file js da includere, o anche scegliere programmaticamente quali controlli usare e impostare selettivamente alcune proprietà piuttosto che altre. Propongo un esempio veramente banale:

switch (Request.Browser.Browser.ToLower())
{
    case "ie":
	    if (Request.Browser.MajorVersion == 7)
	        labelText.Text = "Hello IE7!";
	    else
	        labelText.Text = "Hello IE (time to upgrade!)";
	    break;
    case "firefox":
    	labelText.Text = "Hello Firefox";
	    break;
    default:
	    labelText.Text = "Hello other browser";
	    break;
}

Device/Browser Filter sintax

A partire dalla versione 2 di ASP.NET, è possibile utilizzare una nuova sintassi per i controlli e le proprietà dei controlli. Questa sintassi permette di modificare l’aspetto e le proprietà in base al browser che sta visualizzando la pagina. Proprio come abbiamo fatto da codice, possiamo fare la stessa cosa in fase di progettazione della pagina, purtroppo senza supporto in Design e senza IntelliSense. Ecco un piccolo esempio:

<asp:Button ie:Text="IE Button" runat="server" mozilla:Text="FF Button" />

In teoria ogni proprietà ed ogni classe può essere filtrata in questo modo, tranne quelle esplicitamente dichiarate Filterable=false (vedere la classe del controllo).

Il problema che ho riscontrato più frequentemente è nell’utilizzo del menù, che funziona bene con IE, ma non altrettanto con gli altri browser. Vediamo dunque un esempio che sfrutta i filtri per sistemare i problemi e far funzionare il menù su tutti (quasi) i browser:

<asp:Menu ... >
<ie:Items>
<asp:MenuItem Text="IE Item" />
  </ie:Items>
  <Items>
    <asp:MenuItem Text="Other Item" />
  </Items>

  <DynamicMenuStyle [my styles here] />
  <Safari:DynamicMenuStyle />
  <IE5:DynamicMenuStyle />
  <Safari:DynamicMenuItemStyle ... />
  <IE5:DynamicMenuItemStyle ... />
</asp:Menu>

Si vede chiaramente che si possono filtrare non solo proprietà, ma anche Template e Collection (Classi in genere).

Agire sulle direttive

È possibile anche agire direttamente sulle direttive di una pagina (). In questo modo è possibile ad esempio modificare la proprietà ErrorPage, Theme o Buffer. Ma una cosa furba che possiamo fare è filtrare la proprietà MasterPageFile. Ci prepariamo quindi una diversa per ogni browser (ognuno che vogliamo gestire in maniera diversa naturalmente, altrimenti quante ne dobbiamo fare….. ), nella quale mettiamo il giusto CSS, il giusto Theme, il giusto framework javascript.

<%@ Page Language="C#"
   ie:MasterPageFile="~/MasterPageIE.master"
   mozilla:MasterPageFile="~/MasterPageFirefox.master"
   MasterPageFile="~/MasterPageGeneric.master" %>

Agire sul Web.config

Per personalizzare maggiormente le pagine in base al device, è possibile specificare filtri custom ed usarli per modificare l’output delle pagine. In rete ho trovato solo documentazione che parla di questo utilizzo per dispositivi mobili; quando e se avrò un po’ di tempo vorrei fare dei test anche per altre casistiche.

I metodi per creare nuovi filtri sono 2:

Comparison-Based, con il quale si verifica semplicemente una proprietà comparandola con un valore;

Evaluetor-Delegate-Based, con il quale si utilizza un metodo custom. Il metodo deve semplicemente restituire true o false in base ad una logica che è possibile decidere.

Vorrei evitare di proporre esempi “copia ed incolla” (come ho visto nella maggior parte dei blog), specie per situazioni dove onestamente non ho mai avuto occasione di lavorare. Mi limito quindi a proporre alcuni link dove è possibile trovare documentazione a riguardo:

Mobile Device Capabilities
Developing ASP.NET Mobile Web Pages