Introduzione ai Web Service con .NET

Se ritieni utile questo articolo, considera la possibilitÓ di effettuare una donazione (il cui importo Ŕ a tua completa discrezione) tramite PayPal. Grazie.

I Web Service ("servizi Web" nella traduzione italiana) sono un modo di eseguire chiamate associate a metodi remoti attraverso HTTP. In pratica si tratta di codice utilizzabile non solo da un utente finale "umano" ma anche da altri programmi e l'idea non è certo nuova; esistono infatti diverse tecniche per questo tipo di comunicazione, come ad esempio RPC, DCOM e MSMQ.
Il limite evidenziato da queste tecnologie è che funzionano solo tra sistemi analoghi: MSMQ dialoga solo con MSMQ, un client DCOM solo con un server DCOM e così via. I servizi Web hanno superato questo limite grazie a SOAP (Simple Object Access Protocol), un protocollo basato su XML e quindi universalmente riproducibile, in maniera del tutto indipendente dalla piattaforma tecnologica prescelta. In particolare il .NET Framework mette a disposizione tutto quanto risulta necessario per fornire e/o utilizzare servizi Web.
Nell'esempio seguente vedremo come creare un servizio Web, come testarlo e come realizzare due diverse applicazioni client che utilizzino il servizio (consumer).

Creare un Web Service

Un servizio Web in .NET viene esposto inserendo codice direttamente in un file .asmx o facendo riferimento alle classi di servizi Web da questi file.
Il servizio Web utilizzato come esempio è un semplice convertitore Lire / Euro; verranno perciò esposti due metodi: conversione da Lire ad Euro e conversione da Euro a Lire.
In una cartella virtuale di IIS (ad esempio: http://localhost/webservice) creiamo il file euroconv.asmx:

<%@ Webservice Language="C#" class="EuroConv"%>

using System;
using System.Web.Services;

[WebService (
    Description = "Web Service per la conversione da Lire ad Euro e da Euro a Lire",
    Namespace = "http://www.guru4.net/EuroConv"
)]

public class EuroConv
{
    [WebMethod(Description="Conversione da Lire a Euro")]
    public double Lire2Euro (int Lire)
    {
        return (Lire / 1936.27);
    }

    [WebMethod(Description="Conversione da Euro a Lire")]
    public int Euro2Lire (double Euro)
    {
        return (int)(Euro * 1936.27);
    }
}

In particolare si noti:

  • la direttiva Webservice che indica a .NET che il codice contenuto nella classe dovrà essere esposto come servizio Web

  • la direttiva using System.Web.Serivice per importare il namespace che contiene il codice di infrastruttura utilizzato nei Web Service

  • il modificatore [WebService] nella dichiarazione della classe che implementa il Web Service

  • il modificatore [WebMethod] in ogni metodo che si desidera esporre come servizio Web

Testare il servizio

In .NET i servizi Web possono essere utilizzati dal client pi¨ semplice che abbiate a disposizione: il browser (Internet Explorer 5.5 o superiore).

Visualizzare l'interfaccia del Web service

Digitando nella barra degli indirizzi l'URL del nostro Web Service viene visualizzata una pagina Web che documenta l'interfaccia del servizio:

Verifica del servizio Web attraverso Internet Explorer

I parametri Description specificati nei modificatori del servizio e dei metodi, vengono presentati nella pagina, migliorando decisamente la comprensione delle funzionalità del Web Service.
Qualora nel codice del nostro servizio non avessimo indicato un namespace specifico per il nostro servizio, la suddetta pagina avrebbe mostrato anche informazioni addizionali circa l'uso degli spazi di nomi in .NET e, di default, al nostro Web Service sarebbe stato automaticamente assegnato come namespace http://tempuri.org; anche in assenza di un namespace specifico il servizio funziona correttamente (una volta distribuito in Internet, potrebbero però generarsi conflitti con servizi di altri produttori!)

Autodescrizione dei Web Service: WSDL

Per permettere l'utilizzo del sevizio Web, è necessario che questo fornisca la propria "descrizione" in un file WSDL (Web Service Description Language).
In questo modo gli utilizzatori potranno conoscere i metodi esposti dal servizio, i parametri richiesti, i protocolli supportati, ecc. (un po' come le type library per i componenti COM ma con la differenza sostanziale che WSDL ha valenza anche esterna al mondo Microsoft!)
La semantica e la sintassi del file WSDL sono piuttosto complesse da generare manualmente; la piattaforma .NET permette però di creare in modo totalmente automatico il file WSDL semplicemente richiamando il servizio Web con il parametro WSDL, ad esempio: http://localhost/webservice/euroconv.asmx?WSDL, oppure, facendo riferimento alla figura 1, cliccando su "descrizione del servizio".
Il risultato è il seguente

WSDL del Web Service

La parte più importante della rappresentazione WSDL è data dalla descrizione dei tipi di elemento associati alle richieste e alle risposte:

<types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://www.guru4.net/EuroConv">
        <s:element name="Lire2Euro">
            <s:complexType>
                <s:sequence>
                    <s:element minOccurs="1" maxOccurs="1" name="Lire" type="s:int" />
                </s:sequence>
            </s:complexType>
        </s:element>
        <s:element name="Lire2EuroResponse">
            <s:complexType>
                <s:sequence>
                    <s:element minOccurs="1" maxOccurs="1" name="Lire2EuroResult" type="s:double" />
                </s:sequence>
            </s:complexType>
        </s:element>
        <s:element name="Euro2Lire">
            <s:complexType>
                <s:sequence>
                    <s:element minOccurs="1" maxOccurs="1" name="Euro" type="s:double" />
                </s:sequence>
            </s:complexType>
        </s:element>
        <s:element name="Euro2LireResponse">
            <s:complexType>
                <s:sequence>
                    <s:element minOccurs="1" maxOccurs="1" name="Euro2LireResult" type="s:int" />
                </s:sequence>
            </s:complexType>
        </s:element>
        <s:element name="double" type="s:double" />
        <s:element name="int" type="s:int" />
    </s:schema>
</types>

La descrizione contiene anche le descrizioni dei tipi richiesti dalle risposte e dalle richieste, oltre a vari binding sul servizio che rendono il file piuttosto lungo.

Verificare il funzionamento del servizio

Per testare direttamente i singoli metodi esposti dal Web Service, possiamo semplicemente fare cliccare i relativi link in figura 1; ciò equivale a richiamare il nostro servizio passando al file asmx come parametro "?op=[nome del metodo]". Verrà visualizzata una pagina Web con la descrizione del metodo, un form per l'immissione dei parametri richiesti dal metodo ed esempi di richiesta e risposta nei protocolli supportati (SOAP, GET e POST). Inviando il form (tasto "Richiama" o "Invoke" nella versione inglese di .NET), otterremo la risposta (utilizzando chiamata in GET):

Verificare un metodo del Web Service

Il listener di ASP.NET che indirizza tutte le richieste in arrivo agli oggetti del Web Service accetta indifferentemente tutti e tre i metodi di pacchettizzazione dei dati (HTTP GET, HTTP POST e SOAP). I primi due sono stati implementati per garantire la compatibilità con le versioni precedenti in quanto l'utilizzo di SOAP risulta preferibile poiché semplifica notevolmente la comunicazione tra l'applicazione client ed il servizio. Infatti, come possiamo vedere in figura 3, i Web Service "rispondono" in XML: ricevendo tale informazione via HTTP GET o POST, resta a carico del consumer estrapolare ii dati (ad esempio utilizzando un parser XML); invece, utilizzando SOAP in ambiente .NET, il consumer riceve la richiesta pre-processata, quindi pronta all'uso! Vedremo in concreto i vantaggi di SOAP realizzando un consumer per il serivizio di conversione Euro / Lire.

Creare il consumer del servizio Web

Creiamo due applicazioni distinte che utilizzino il nostro Web Service: una pagina Web ed un'applicazione Windows. Nel primo caso utilizzeremo solo il blocco note e l'SDK del .NET framework, mentre nel secondo caso utilizzeremo Visual Studio .NET

Client ASP.NET

Per realizzare un'applicazione Web che utilizzi il servizio Web dobbiamo creare una classe proxy ed una pagina ASP.NET

La classe proxy

Dato il file WSDL del servizio Web, possiamo creare una classe che faccia da proxy per la nostra pagina ASP.NET, ovvero un componente che ci permetta di accedere in modo trasparente al Web Service, senza preoccuparci delle modalità con le quali questo viene chiamato ed utilizzato; la classe proxy metterà quindi a disposizione il servizio esattamente come se fosse un componente da noi realizzato ed utilizzato nel progetto.
L'utility a riga di comando wsdl.exe dell'SDK di .NET ci permette di generare una classe proxy:

wsdl /language:CS http://localhost/webservice/euroconv.asmx?WSDL

Il parametro language ci permette di specificare uno dei linguaggi supporati dal .NET framework (nell'esempio si è richiesto a wsdl.exe di generare una classe C#).
Il risultato della suddetta operazione è la generazione del file EuroConv.cs, contenente il codice della classe proxy per il servizio EuroConv:
A questo punto non ci resta che compilare il file di cui sopra, sempre utilizzando l'SDK:

csc /t:library /out:EuroConv.dll EuroConv.cs /r:system.dll /r:system.xml.dll /r:system.web.services.dll

Abbiamo cioè compilato la classe come libreria di classi (/t:library) indicando come risultato della compilazione EuroConv.dll ed utilizzando i metadata specificati nei parametri /r
A questo punto il file EuroConv.dll dovrà essere inserito nella cartella /BIN dell'applicazione che lo utilizzerà, ad esempio http://localhost/consumer/bin/EuroConv.dll

La pagina ASP.NET

Realizziamo una semplice pagina ASP.NET con un form server side che comprenda:

  • cmbCurrency: casella a discesa per la selezione del tipo di valuta di partenza (Euro o Lire); in base alla valuta selezionata verrà invocato il metodo Euro2Lire() o Lire2Euro()

  • txtValue: casella di testo per l'immissione della valuta da convertire

  • lblResult: etichetta in cui visualizzare il risultato della conversione

  • btnConvert: pulsante per richiamare il servizio Web di conversione

Il listato seguente presenta il codice della pagina euroconvertitore.aspx, che potremo raggiungere all'indirizzo http://localhost/consumer/euroconvertitore.aspx:

<%@ Page Language="C#"%>
<%@ import Namespace="System" %>
<%@ import Namespace="System.Collections" %>
<%@ import Namespace="System.ComponentModel" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Drawing" %>
<%@ import Namespace="System.Web" %>
<%@ import Namespace="System.Web.SessionState" %>
<%@ import Namespace="System.Web.UI" %>
<%@ import Namespace="System.Web.UI.WebControls" %>
<%@ import Namespace="System.Web.UI.HtmlControls" %>
<script runat="server">
    public void Convert(Object sender, EventArgs e)
    {
        EuroConv converter = new EuroConv();
        string res = "";
        string currency = "";
        if(cmbCurrency.SelectedItem.Text.ToLower() == "euro")
        {
            double val = System.Double.Parse(txtValue.Text);
            res = converter.Euro2Lire(val).ToString();
            currency = "Lire";
        }
        else
        {
            int val = System.Int32.Parse(txtValue.Text);
            res = converter.Lire2Euro(val).ToString();
            currency = "Euro";
        }
        lblResult.Text = res + " " + currency;
        converter = null;
    }
</script>
<html>
<head>
    <title>Euro Convertitore</title>
</head>
<body>
    <form method="post" runat="server">
        <asp:DropDownList id="cmbCurrency" runat="server">
            <asp:ListItem Value="Euro" Selected="True">Euro</asp:ListItem>
            <asp:ListItem Value="Lire" Selected="False">Lire</asp:ListItem>
        </asp:DropDownList>
        <asp:TextBox id="txtValue" runat="server" text=""></asp:TextBox>
        <br />
        <asp:Button id="btnConvert" onclick="Convert" runat="server" Text="converti..." Width="54px"></asp:Button>
        <asp:Label id="lblResult" runat="server" BorderWidth="1px" BorderColor="Gray" BorderStyle="Solid" Width="142px"></asp:Label>
    </form>
</body>
</html>

Si noti che l'oggetto "EuroConv" viene utilizzato come fosse una normale classe dell'applicazione:

EuroConv converter = new EuroConv();

Il risultato sarà il seguente:

La pagina ASP.NET consumer del servizio Web

Client Windows

Realizziamo ora un'applicazione Windows analoga alla pagina Web di cui sopra.
Apriamo Visual Studio .NET e creiamo un nuovo "Progetto C# - Applicazione Windows" con nome "EuroConvertitore". Rinominiamo Form1 in frmEuro e posizioniamo all'interno del form i controlli:

  • cmbCurrency: casella a discesa per la selezione del tipo di valuta di partenza con due Items: Euro e Lire; in base alla valuta selezionata verrà invocato il metodo Euro2Lire() o Lire2Euro()

  • txtValue: casella di testo per l'immissione della valuta da convertire

  • lblResult: etichetta in cui visualizzare il risultato della conversione

  • btnConvert: pulsante per richiamare il servizio Web di conversione

Il form Windows in modalità "Progettazione"

Visual Studio .NET permette di utilizzare in modo semplice ed intuitivo un servizio Web al'interno della nostra applicazione; è infatti sufficiente utilizzare la procedura guidata per l'inserimento di un nuovo riferimento Web, raggiungibile indifferentemente dal menù "Progetto - Aggiungi riferimento Web..." oppure dal menù contestuale (tasto destro del mouse) di "References" nella finestra "Esplora soluzioni" (vedi Fig. 6)
Nel wizard che ci viene proposto è sufficiente specificare l'indirizzo del web service (nel nostro esempio: http://localhost/webservice/euroconv.asmx) e confermare premendo il tasto "Aggiungi riferimento"

Aggiunta di un riferimento Web al servizio

Facciamo doppio click sul pulsante "converti..." (btnConvert) ed inseriamo il codice C# per effettuare la conversione della valuta utilizzando il servizio Web:

private void btnConvert_Click(object sender, System.EventArgs e)
{
    EuroConvertitore.localhost.EuroConv converter = new EuroConvertitore.localhost.EuroConv();
    string res = "";
    string currency = "";
    if(cmbCurrency.Text.ToLower() == "euro")
    {
        double val = System.Double.Parse(txtValue.Text);
        res = converter.Euro2Lire(val).ToString();
        currency = "Lire";
    }
    else
    {
        int val = System.Int32.Parse(txtValue.Text);
        res = converter.Lire2Euro(val).ToString();
        currency = "Euro";
    }
    lblResult.Text = res + " " + currency;
    converter = null;
}

A questo punto non ci resta che compilare la nostra applicazione selezionando "Genera EuroConvertitore" dal menù "Genera" di Visual Studio .NET.