Windows Communication Foundation: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica |
Nessun oggetto della modifica |
||
Riga 25:
Dopo tanta teoria, è arrivato il momento di passare al codice. Come esempio verrà creato un servizio che riceve in input un codice prodotto e restituisce tutte le informazioni legate al prodotto con quel codice.
La prima cosa da fare quando si costruisce un servizio con WCF è stabilire il contratto di comunicazione tramite interfaccia che nel nostro caso è la seguente:
{
[ServiceContract]
public interface IContract {
Riga 30 ⟶ 31:
Product GetProductById(string IdProduct);
}
}
Come detto in precedenza, è importante notare l'uso degli attributi.
Una volta stabilito quali servizi mettere a disposizione, si determina quali dati l'entità Product debba pubblicare e quali invece debba mantenere privati:
{
[DataContract]
public class Product{
Riga 55 ⟶ 57:
}
}
}
Qui la cosa principale su cui porre attenzione è la possibilità di pubblicare la proprietà Price nonostante questa sia privata. Infatti, quando il client riceverà le informazioni i dati dell'entità Product saranno tre: IdProduct, Name e Price e non Category nonostante sia pubblico. Poiché gli attributi vengono utilizzati dal runtime di WCF per serializzare i dati, questi sono il naturale contenitore di alcune proprietà che permettono di controllare questo processo. Infatti possiamo definire come chiamare l'elemento che contiene la classe o come chiamare i singoli attributi che espongono i valori delle proprietà.
Possono essere definite anche altre proprietà come l'ordine, l'obbligatorietà di un dato e altro ancora.
Nonostante questo buon livello di controllo a volte si ha bisogno di un controllo totale sul processo di serializzazione, in questo caso la cosa migliore è marcare l'interfaccia con l'attributo XmlSerializerFormat che invece di sfruttare il serializzatore di default utilizza il serializer standard del .NET Framework che viene utilizzato anche per i WebService Asmx.
A questo punto l'interfaccia è pronta, le classi sono stabilite, manca solo l'implementazione del codice per restituire i dati:
{
public class ProductRetriever : IContract {
public Product GetProductById(string IdProduct){
Riga 69 ⟶ 72:
}
}
}
La parte relativa al codice è finita. Per realizzare un servizio WCF questo è tutto il codice di cui abbiamo bisogno. Come si vede, non c'è alcun riferimento al tipo di tecnologia di trasmissione dati o codice di serializzazione o altro ancora.
Hosting del servizio
Riga 75 ⟶ 78:
Come già accennato, la magia di WCF sta in parte nel codice semplificato ed unificato per ogni modalità di comunicazione, e in parte nel fatto che semplicemente cambiando la configurazione si può passare da http a TCP, da messaggi in chiaro a messaggi criptati, ecc ecc. In realtà tutto quello che si può configurare da file può essere realizzato anche da codice, ma non è buona pratica cablare nell'applicazione queste informazioni. Può essere invece molto utile realizzare una form di gestione della configurazione al fine di rendere la modifica più semplice in fase di deploy.
Il posto naturale dove inserire le informazioni di configurazione è il file .config all'interno del quale va inserito un nodo system.serviceModel che è il contenitore di ogni impostazione:
{
<configuration>
<system.serviceModel>
Riga 87 ⟶ 91:
</system.serviceModel>
</configuration>
}
Dal file di configurazione possiamo ricavare tutte le informazioni necessarie per il funzionamento del servizio e utilizzarle da codice per istanziare il servizio utilizzando l'oggetto ServiceHost in una semplice console application:
{
using (ServiceHost serviceHost = new ServiceHost(typeof(WinFXItalia.Library.ProductRetriever), "http://localhost/ws/svc")) {
serviceHost.Open();
}
}
Una volta avviata l'applicazione questa resterà in ascolto in base alle informazioni specificate nel .config relative all'address, binding e contract.
Riga 105 ⟶ 111:
Attualmente, Visual Studio non ha un'interfaccia grafica per costruire in automatico il proxy, quindi la sola possibilità è utilizzare il tool SvcUtil.exe da riga di comando. Questo tool risulta molto comodo perché non solo crea automaticamente il proxy, ma anche il file di configurazione che il client può utilizzare per la connessione. Quest'ultima frase lascia capire che anche il client può essere pilotato da configurazione senza bisogno di codice esattamente come si fa con il servizio.
Avendo anche il client un EndPoint, le informazioni da pubblicare sono le stesse del servizio: l'Address, il Binding ed il Contract. I primi due corrispondono ai dati dell'endpoint utilizzato dal servizio, mentre il contract corrisponde alla classe automaticamente generata nel proxy. L'altra differenza rispetto alla configurazione del servizio è il nome del nodo principale che contiene i dati: invece di avere un nodo <services> con diversi <service> innestati, esiste un nodo client con tutti gli endpoint figli:
{
<configuration>
<system.serviceModel>
Riga 115 ⟶ 122:
</system.serviceModel>
</configuration>
}
Anche qui, una volta stabilita l'interfaccia si passa al codice per invocare il servizio e ricevere i dati. Nel nostro caso il client sarà una classica Windows Application che al click di un bottone invoca il servizio.
{
using (ContractProxy proxy = new ContractProxy()) {
WinFXItalia.Library.Product p = proxy.GetProductById("1");
}
}
Questo snippet illustra come il codice sia in realtà molto banale e simile a quello che si fa ora per i WebService: si crea un'istanza del proxy e si invoca il metodo. Anche per il client, qualunque sia il protocollo, i Behaviours e altro ancora, sarà sempre compito di WCF eseguire la pipeline che porta alle trasformazioni e all'invio fisico del messaggio e viceversa alla ricezione della risposta, ripercorrendo la pipeline al contrario.
|