versione italiana versione italiana
english version english version

Web Services from a .NET Perspective (Parte 1/3)

Il nostro primo Web Service
 
Per realizzare un Web Service sfruttando il Framework .NET è sufficiente appoggiarsi alle classi presenti nel Namespace System.Web.Services e realizzare un documento con estenzione ASMX da pubblicare in una cartella accessibile via Web.
L'estensione ISAPI di ASP.NET (vedi articolo di Roberto Brunetti a tal proposito) verrà richiamata in conseguenza dell'estensione ASMX e passerà il controllo al Worker Process di ASP.NET per la vera gestione del Web Service. Un Web Service .NET ridotto ai minimi termini si presenta come il seguente:
 

using System;
using System.Web.Services;
public class wsTest
{
[WebMethod()]
public String TextEcho(String sData)
{
return(sData);
}
}
 
I punti fondamentali del codice precedente sono:  
  • La direttiva di pagina @WebService e l'indicazione della classe associata al servizio che si vuole esporre
  • L'utilizzo del Namespace System.Web.Services, che contiene le classi che rendono possibile la creazione dei servizi
  • L'attributo WebMethod associato al metodo pubblico TextEcho della classe, affinchè il motore di ASP.NET esponga tale metodo e lo descriva nel WSDL del servizio
 
Per provare un servizio come il precedente è sufficiente salvarlo in una cartella web per esempio con nome wsTest01.ASMX e richiamarlo da un browser. Proviamo: http://devlab.devleap.it/PaoloPi/ws01/wsTest01.asmx
 
Come si può vedere si ottiene in modo automatico e per noi trasparente una pagina HTML di presentazione del servizio appena costruito.
Da questa pagina possiamo:  
  • Vedere la lista dei servizi esposti tramite il file ASMX
  • Consultare un WSDL generato automaticamente, al volo, per noi dal Framework .NET
  • Provare i servizi invocandoli dal browser, fornendo eventuali parametri tramite una normalissima form HTML

Non male !
 
Cerchiamo di capire cosa accade
 
Cosa succede in realtà quando scriviamo del codice come quello precedente in un documento ASMX ?
L'attributo WebMethodAttribute che abbiamo associato al metodo della classe fa sì che il motore di ASP.NET renda accessibile via Web quel metodo. La classe che lo contiene viene a sua volta esposta come Web Service grazie all'indicazione inserita nella dichiarazione @WebService.
Sia la classe che i metodi che vogliamo esporre via Web sono configurabili tramite attributi. In particolare all'interno del Namespace System.Web.Services troviamo quattro classi di cui due sono in questo momento per noi le più interessanti:  
  • WebServiceAttribute: ci permette di fornire un nome, una descrizione ed il Namespace XML di default per il nostro WebService
  • WebMethodAttribute: ci consente di indicare che un metodo dovrà essere esposto come servizio, oltre ad una serie di informazioni sulla gestione dello stato, della cache, della transazionalità, la gestione del buffer, un alias per il metodo e informazioni descrittive del servizio.
 
Quindi il sorgente del nostro servizio può diventare:  

using System;
using System.Web.Services;
[WebService(Description="Web Service di Test",
Namespace="http://www.devleap.it/NS/wsTest",
Name="DevLeap-wsTest")]
public class wsTest
{
[WebMethod(Description="Questo metodo restituisce la Eco del testo fornito")]
public String TextEcho(String sData)
{
return(sData);
}
}
Vediamo cosa cambia: http://devlab.devleap.it/PaoloPi/ws01/wsTest02.asmx
 
E' immediato notare che la pagina di presentazione del servizio è ora priva di segnalazioni relative al Namespace (che è stato correttamente da noi indicato come http://www.devleap.it/NS/wsTest) è non sarà più il generico http://tempuri.org/ come nel caso precedente. Se proviamo ora ad invocare il servizio otterremo come risultato il seguente documento XML, che contiene proprio un riferimento al Namespace del nostro Web Service, per distinguerne il risultato da quello di qualsiasi altro servizio.  

http://www.devleap.it/NS/wsTest">fdssfgsf
 
Un servizio più serio
 
Proviamo ora a realizzare un Web Service un pochino più serio del precedente. Per esempio pensiamo ad un servizio che calcoli il codice fiscale di un cittadino italiano.
Per informazioni sull'algoritmo di calcolo e controllo del codice fiscale vi rimando ad uno dei mille siti web che ne parlano diffusamente e che potete trovare con un qualsiasi motore di ricerca. Nel nostro esempio non implementeremo il codice reale del servizio ma faremo solo una simulazione.
Pensiamo ad un'ipotesi di classe CodiceFiscale che esponga due metodi:  
  • CalcolaCodice: per calcolare il codice fiscale di un cittadino sulla base dei suoi dati (nome, cognome, sesso, data di nascita, luogo di nascita)
  • ControllaCodice: per controllare che un codice fiscale sia valido e per ottenere le informazioni salienti sul possesore del codice (iniziali del nome e cognome, sesso, data di nascita, luogo di nascita)
 
Un servizio come questo necessità di lavorare con un tipo complesso che descriva il generico cittadino nel modo seguente:  
public class Cittadino
{
public String Nome;
public String Cognome;
public String Sesso;
public DateTime DataNascita;
public String ComuneNascita;
public Cittadino(){}
}
 
A questo punto però non potremo restituire con il metodo ControllaCodice o ricevere in ingresso al metodo CalcolaCodice un tipo base semplice. Ecco che dovremo appoggiarci alle possibilità offerte dalla serializzazione XML (vedi articoli a riguardo) per rappresentare sotto forma di XML una classe come quella precedente. Il nostro servizio, dal punto di vista del codice sorgente, potrà presentarsi come il seguente:  

using System;
using System.Web.Services;
[WebService(Description="Web Service per il calcolo ed il controllo del Codice Fiscale",
Namespace="http://www.devleap.it/NS/CodiceFiscale",
Name="DevLeap - Codice Fiscale")]
public class CodiceFiscale
{
[WebMethod(Description="Questo metodo restituisce il codice fiscale di un
cittadino sulla base dei suoi dati")]
public String CalcolaCodice(Cittadino oCittadino)
{
// Restituisco sempre il mio codice fiscale :-) !
return("PLRPLA75L03B157T");
}
[WebMethod(Description="Questo metodo restituisce i dati di un cittadino sulla
base del suo codice fiscale")]
public Cittadino ControllaCodice(String sCodice)
{
// Se il codice è di lunghezza diversa da 16 sicuramente è errato
if (sCodice.Length != 16) return(null);
// Altrimenti ricavo i dati sul codice che sono sempre i miei :-) !
Cittadino oCittadino = new Cittadino();
oCittadino.Nome = "Paolo";
oCittadino.Cognome = "Pialorsi";
oCittadino.Sesso = "M"; // Almeno dicono ...
oCittadino.DataNascita = DateTime.Parse("03/07/1975");
oCittadino.ComuneNascita = "Brescia";
return(oCittadino);
}
}
public class Cittadino
{
public String Nome;
public String Cognome;
public String Sesso;
public DateTime DataNascita;
public String ComuneNascita;
public Cittadino(){}
}
 
Come si vede il tipo Cittadino è accettato in ingresso dal metodo CalcolaCodice ed è restituito dal metodo ControllaCodice. Se proviamo a controllare il WSDL che ci viene restituito dal Framework (vedi http://devlab.devleap.it/PaoloPi/ws01/CodiceFiscale.asmx?WSDL) possiamo immediatamente notare che il tipo Cittadino viene correttamente rappresentato tramite XSD per conto nostro:  
      








 
Possiamo anche notare che dalla pagina di presentazione di questo nuovo Web Service (http://devlab.devleap.it/PaoloPi/ws01/CodiceFiscale.asmx) che il metodo CalcolaCodice, dal momento che richiede in ingresso un tipo complesso, non è invocabile dalla pagina di test del servizio via HTTP GET, ma dovrà essere richiamato da un client SOAP tramite HTTP POST di una richiesta SOAP.  
 
Nella prossima parte di articolo vedremo come viene costruita la pagina di descrizione del servizio e come personalizzare il comportamento del servizio (session state, buffer, caching, transazionalità).  
 
Nel frattempo puoi provare il Web Service per il calcolo ed il controllo dei Codici Fiscali ai seguenti indirizzi:
http://devlab.devleap.it/PaoloPi/CodiceFiscale/CodiceFiscale.aspx
http://devlab.devleap.it/PaoloPi/CodiceFiscale/wsCodiceFiscale.asmx