ABC di WCF (con screencast)

In questo articolo vediamo come realizzare un'applicazione WCF partendo dall'esposizione dei principi di base, costruendone uno da zero in C# con VS2008, installandolo su IIS 7 e infine consumandolo con un client WPF.

Vi suggerisco di vedere prima lo screencast che segue -dura circa 10 minuti-, per avere un'idea di come si realizza un'applicazione di questo tipo, e poi provare a realizzare nuovamente la stessa seguendo passo passo il resto di questo post. Trovate i sorgenti del progetto a questo link.

Una volta predisposta una macchina per creare ed ospitare applicazioni WCF, il primo passo per capire come funziona WCF consiste nel studiarne l'ABC, non solo in senso figurato:

  • A sta per Address, ovvero DOVE avviene la comunicazione; nella pratica, questo è l'URL utilizzato internamente per mappare richieste e risposte.
  • B sta per Binding, cioè COME si comunica: tramite HTTP, TCP, NamedPipes, MSMQ, o altro protocollo che client e server entrambi capiscono.
  • C è il Contratto: che COSA client e server si dicono; in particolare, esistono due tipi di contratto:
    • Data Contract: le informazioni che client e server si scambiano, la cui struttura è indicata nello schema del servizio;
    • Service Contract: i metodi invocati sul vostro servizio dal client, la cui firma (in gergo signature) è contenuta nel WSDL.

Partiamo lanciando Visual Studio 2008, ricordando di lanciarlo in modalità Amministratore se intendete utilizzare il server WEB della vostra macchina Windows Vista; ciò non è necessario se utilizzate il Personal Web Server.

Creiamo un nuovo progetto di tipo WCF (File-New Web Site...), scegliamo un nome e premiamo OK. Noterete che, come spesso succede, il progetto non è esattamente vuoto perché Visual Studio ci ha favorito inserendo qualche piccola porzione di codice, che normalmente lo sviluppatore deve sempre scrivere; in questo caso, però, poiché vogliamo capire esattamente i dettagli di WCF, lo "puliremo" quasi per intero.

Apriamo innanzi tutto il file App_Code\IService.cs e rimuoviamo tutto il codice tranne gli using iniziali che referenziano i namespace. In questo file si specifica l'interfaccia del servizio in termini di dati e metodi attraverso cui il servizio si espone all'esterno; notate la corrispondenza fra questi due termini e i due tipi di contratto che ho indicato sopra con lo stesso colore.

Partiamo con il Data Contract: definiamo due tipi che useremo per comunicare; potremmo usare tipi semplici come string e int, ma per fare un esempio semplice e al tempo stesso estensibile userò però due classi, ciascuna con un membro pubblico: chiamerò la prima Richiesta e la seconda Risposta:

wcf-01

Ora, affinché la classe sia serializzabile, l'autore deve definire il data contract che dicevo sopra. L'attributo [DataContract], applicato ad una classe o ad un tipo, specifica che la classe (o il tipo) definisce o implementa un data contract ed è serializzabile da un serializatore come System.Runtime.Serialization.DataContractSerializer; in modo simile, l'attributo [DataMember] deve essere applicato ad ogni membro pubblico che si vuole esporre della classe serializzata. Ecco quindi come devono essere modificate le due classi sopra per diventare parte del data contract:

wcf-02

Oltre al Data Contract io voglio ora implementare il Service Contract: in altre parole, voglio esporre un metodo. Tale funzione, che chiamerò RendiMaiuscolo, accetta un oggetto di classe Richiesta e restituisce un oggetto di classe Risposta creato all'interno della funzione stessa; si noti che così come il Data Contract richiede la coppia [DataContract] / [DataMember], in modo simile il Service Contract richiede l'attributo [ServiceContract] prima della definizione dell'interfaccia, e [OperationContract] per la definizione del metodo; in pratica, scriveremo così la sua signature:

wcf-03

 

Il prossimo passo consiste nell'implementare il contratto (in particolare il suo Service Contract) appena definito: apriamo il file App_Code\Service.cs, rimuoviamo tutto il codice e implementiamo l'interfaccia; si può anche chiedere a Visual Studio di generare il metodo automaticamente premendo il tasto destro sul nome dell'interfaccia IService da cui si eredita, come mostrato di seguito:

wcf-04

Le seguenti tre righe di codice creano un nuovo oggetto di tipo Risposta ed assegnano al suo membro StringaRisposta la stringa contenuta nell'oggetto richiesta che viene passato al metodo, trasformata in maiuscolo:

wcf-05

Per completezza di informazione aggiungo che l'ultimo snippet di codice avrebbe potuto contenere l'attributo [ServiceBehaviour] prima della definizione della classe Service che deriva dall'interfaccia IService, e l'attributo [OperationBehaviour] prima dell'implementazione del metodo RendiMaiuscolo; tuttavia, questi attributi sono opzionali.

Con l'ultima operazione abbiamo terminato la scrittura del servizio; provate a compilarlo, non devono esserci errori. È giunto quindi il momento di consumarlo.

A questo proposito aggiungiamo alla soluzione un nuovo progetto di tipo WPF (nel mio caso l'ho chiamato WpfApplication1) e un riferimento all'oggetto che implementa l'interfaccia IService appena sviluppata; si noti che premendo il bottone Discover, Visual Studio analizza la soluzione e ne mostra i servizi disponibili, quindi non dobbiamo far altro che selezionare l'oggetto che ci serve specificando un namespace per noi significativo (io l'ho chiamato ServizioDiTest):

wcf-06   wcf-07

Da questo momento in avanti è possibile utilizzare proprietà e metodi pubblici del servizio attraverso l'oggetto ServizioDiTest.ServiceClient.

Per testarlo, aggiungete un oggetto TextBox e un Button nel file Window1.XAML:

wcf-08

in modo da generare l'event handler dell'evento Click nel file Window1.xaml.cs, che riempiremo con queste 6 righe di codice che instanziano il servizio, usano il suo riferimento per creare l'oggetto richiesta e per creare un riferimento risposta alla classe Risposta di cui il servizio crea l'istanza nel metodo RendiMaiuscolo.

image

Impostate ore l'applicazione WPF come startup project e lanciatela: premendo il bottone, la stringa verrà convertita in maiuscolo:

wcf-09