ASP.NET AJAX ha ormai raggiunto un livello di diffusione tale che progettare oggigiorno un'interfaccia basata su ASP.NET che non ne tragga beneficio è quasi impensabile. Sebbene il successo di questa infrastruttura sia in gran parte dovuto alla semplicità d'uso del noto controllo UpdatePanel, spesso progetti di una certa rilevanza necessitano di soluzioni avanzate, sviluppate ed ottimizzate a seconda delle esigenze.
Già da tempo sono disponibili in rete molte suite di controlli ASP.NET AJAX, destinate agli sviluppatori; di queste, alcune sono commerciali ed altre, come la nota AJAX Control Toolkit, sono gratuite ed open source. Entrambe le tipologie di soluzioni, ad ogni modo, sfruttano il supporto che la piattaforma mette a disposizione per creare controlli custom.
Rispetto alle conoscenze richieste a chi sviluppa controlli ASP.NET, realizzare un controllo custom in ASP.NET AJAX richiede, in aggiunta, una forte familiarità con le tecnologie web lato client, JavaScript e DHTML in primis. Tipicamente, lo sforzo relativo allo sviluppo di controlli di questa tipologia si concentra maggiormente proprio sull'impiego di queste ultime tecnologie, sulle quali il framework stesso fonda le proprie radici.
Il modello client
Al cuore di ASP.NET AJAX risiede infatti una sofisticata libreria di codice ECMAScript (JavaScript), che estende il modello ad oggetti ed include un nuovo sistema di tipi per questo linguaggio: in maniera simile al .NET Framework, è possibile di fatto definire spazi dei nomi, interfacce, enumerazioni, utilizzare l'ereditarietà e sfruttare la reflection.
La libreria contiene inoltre un elevato numero di classi che consentono di colmare in qualche modo il gap funzionale tra codice managed e codice JavaScript, in passato spesso lamentato dagli sviluppatori ASP.NET. Dal punto di vista architetturale, la gerarchia dei tipi definiti nella libreria JavaScript di ASP.NET AJAX si dirama con modalità simili a quella dell'ambiente .NET: oltre al namespace Sys, capostipite di tutti i namespace definiti dalla libreria e contenitore delle classi di base del runtime del framework, una serie di namespace delinea i contorni delle funzionalità extra esposte dalla piattaforma: Sys.Net, Sys.Serialization, Sys.Services, Sys.WebForms, Sys.UI.
Namespace | Sintesi delle funzionalità esposte |
Namespace globale | Supporto per i namespace, l'ereditarietà e l'implementazione delle interfacce. Estensione dei tipi primitivi Javascript ed aggiunta di nuove funzionalità a quelli esistenti (Function e Type, String, Date, Array, Boolean, Number, Error, Object). |
Sys | Modello applicativo a componenti, supporto per il cleanup degli oggetti (Sys.IDisposable), gestione dei delegati multicast, della globalizzazione (Sys.CultureInfo) e supporto per il debugging (Sys.Debug). |
Sys.Net | Layer di comunicazione asincrona: supporto per il caricamento di dati da web service. |
Sys.Serialization | Funzionalità di serializzazione e deserializzazione in formato JSON di oggetti JavaScript; JSON - un acronimo che sta per JavaScript Object Notation - è un formato di interscambio di informazioni strutturate, in grado di rappresentare oggetti ed altre strutture di dati attraverso semplici stringhe. |
Sys.Services | Espone i servizi di autenticazione e profilazione di ASP.NET direttamente alle classi JavaScript, utilizzando, dietro le quinte, i metodi di un web service esposto dalle estensioni lato server di ASP.NET AJAX. |
Sys.WebForms | Gestisce il modello di rendering parziale e consente di prendere parte al ciclo di vita delle richieste, registrandosi ad appositi eventi. |
Sys.UI | Permette l'interazione con gli elementi dell'interfaccia utente, compresi i controlli HTML e gli eventi ad essi associati. Contiene inoltre alcune classi che facilitano le operazioni di localizzazione e riposizionamento di tali controlli all'interno del layout della pagina ospitante. |
Nonostante la complessità delle funzionalità esposte e la semplicità d'uso che ne caratterizza l'implementazione, tutte le classi della libreria ASP.NET AJAX sono cross browser e non richiedono test espliciti dello user agent (sniffing) da parte degli utilizzatori. Molti dei metodi esposti dalle innumerevoli classi della libreria hanno una firma molto simile a quella delle corrispondenti classi in ambiente .NET; la classe String, ad esempio, espone il metodo format(format, args), utilizzato per la formattazione delle stringhe. A parte il casing, necessario per rispettare le convenzioni di nomenclatura del linguaggio, la funzionalità non cambia ed è possibile utilizzarne l'implementazione nel proprio codice JavaScript come segue:
var formattedDate = String.format('{0:dd MMMM yyyy}', new Date()); alert(formattedDate); // 13 novembre 2007
L'ereditarietà nel modello client
Definire una propria gerarchia di tipi utilizzando ASP.NET AJAX richiede, al di là della nota sintassi JavaScript per la definizione dei prototipi di classe, l'impiego dei metodi della classe Type, del namespace globale. Lo scopo di questa classe, probabilmente la più importante dell'intera libreria JavaScript, è di consentire, come anticipato, l'estensione del modello ad oggetti del linguaggio: ASP.NET AJAX impiega, infatti, una serie di strutture e liste che mantengono riferimenti a tutti i tipi disponibili nel sistema, alle gerarchie che tra di questi esistono ed alle interfacce da questi implementate. Analogamente a .NET, il supporto si limita alla sola ereditarietà singola (una sola classe base diretta), ma consente di implementare più interfacce per tipo.
Per poter utilizzare l'ereditarietà in ASP.NET AJAX, ciascun tipo deve notificare al sistema la propria definizione, fornendo dettagli in merito alla classe di base - se presente - e sulle eventuali interfacce implementate; la notifica comporta una chiamata al metodo Type.registerClass(typeName, baseType, interfaceTypes), dove typeName corrisponde al nome della classe che si desidera notificare al sistema, baseType è il tipo di base e interfaceTypes un array di interfacce che il tipo implementa. La definizione di un'interfaccia invece prevede la chiamata al metodo Type.registerInterface(typeName), che accetta come unico parametro il nome del tipo desiderato.
Una semplice classe di limitate funzionalità potrebbe dunque essere definita ed utilizzata come segue:
Person = function() { }; Person.prototype = { sayHello: function() { return 'Hello world!'; } }; Person.registerClass('Person'); // Esempio di utilizzo di Person var person = new Person(); alert(person.sayHello()); // Hello world!
L'interazione con le classi base
L'utilizzo dell'ereditarietà all'interno delle proprie classi presuppone, a causa dei limiti del linguaggio JavaScript a cui il framework cerca di porre rimedio (non esiste la keyword base, come in altri linguaggi orientati agli oggetti), un'interazione esplicita con il runtime di ASP.NET AJAX; in particolare, il costruttore di ciascuna classe deve richiamare la funzione Type.initializeBase(instance, baseArguments) al fine di risolvere l'ereditarietà e richiamare il costruttore della classe di base, fornendo un riferimento all'istanza corrente e ad eventuali parametri attesi da quest'ultimo. I metodi definiti nelle classi base devono essere richiamati da quelle derivate mediante la funzione Type.callBaseMethod(instance, name, baseArguments), che, in aggiunta alla funzione appena vista, richiede il nome del metodo da richiamare.
Ecco come potrebbe dunque apparire un'altra semplice classe, derivata da quella dell'esempio precedente:
Developer = function() { Developer.initializeBase(this); }; Developer.prototype = { sayHello: function() { return 'A developer says: ' + Developer.callBaseMethod(this, 'sayHello'); } }; Developer.registerClass('Developer', Person); // Esempio di utilizzo di Developer var developer = new Developer(); alert(developer.sayHello()); // A developer says: Hello world!
Attenzione: Questo articolo contiene un allegato.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.