I contract
WCF è stato pensato sin dall’inizio tenendo in mente le architetture orientate ai servizi. In una tecnologia come questa è molto importante mettere a disposizione un’interfaccia software che l’utilizzatore del servizio ed il servizio possono utilizzare per comunicare. In WCF quest’interfaccia di scambio è il contratto.
I contratti non stabiliscono solo quali operazioni si possono invocare su un servizio, ma anche come e quali dati si debbano scambiare. Da questa considerazione si evince che esistono diverse tipologie di contratti racchiuse in tre tipologie: ServiceContract, DataContract e MessageContract.
I ServiceContract definiscono il servizio e tutte le API che mette a disposizione. La definizione di un simile contratto vede la sua naturale definizione in un’interfaccia .NET da implementare. Di per se, un’interfaccia non ha alcun senso parlando in termini di Service Oriented Architecture, infatti, pur definendo metodi e proprietà , non stabilisce se questi debbano essere resi pubblici o meno. Bisogna ricordare che in con SOA la visibilità di un metodo o di una proprietà all’interno di una classe, non ha alcun collegamento con la visibilita che può avere all’interno del servizio. A seconda dei casi, un metodo privato di una classe potrebbe diventare un’API del servizio, mentre un metodo pubblico della stessa classe potrebbe non essere pubblicato dal servizio.
In WCF, per definire i metodi da pubblicare, bisogna decorarli con opportuni attributi dichiarati nella definizione dell’interfaccia. Gli attributi da utilizzare sono ServiceContract con la quale marcare l’interfaccia e OperationContract per ogni metodo da pubblicare. Una volta che è stato stabilito quali operazioni mettere a disposizione dei client, arriva il momento di definire quali informazioni debbano essere pubblicate. Questo è compito dei DataContract. Supponiamo che un servizio pubblichi un metodo che dato il codice fiscale ritorni i dati della persona associata. Nel DomainModel l’oggetto Persona contiene informazioni come Nome, Cognome, Data di Nascita e altro ancora, tuttavia può nascere l’esigenza di non pubblicare tutti i dati della persona ma soltanto quelli che si ritengono opportuni. Per ottenere un risultato del genere bisogna decorare sia la classe che le sue proprietà con attributi, più approfonditamente alla classe va applicato l’attributo DataContract e alle proprietà l’attributo DataMember.
Per default, tutte le proprietà di una classe vengono mappate all’interno del corpo di un messaggio. A seconda delle esigenze, può capitare che si debbano piazzare delle informazioni nelle intestazioni invece che nel corpo; questo mapping tra le classi ed il formato del messaggio viene impostato tramite MessageContract. Anche in questo caso l’impostazione di queste opzioni avviene tramite attributi e, più precisamente, MessageContract per la classe e MessageBody o MessageHeader per le proprietà .
Un’occhiata al codice
Dopo tanta teoria, è arrivato il momento di passare al codice. Come esempio verrà creato un servizio che riceve in input una matricola e restituisce tutte le informazioni legate allo studente universitario con quella matricola.
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 { [OperationContract] Studente GetStudenteByMatricola(Int32 Matricola); }
[DataContract] public class Studente{ [DataMember] public Int32 Matricola{ get { return _matricola; } set { _matricola= value; } } [DataMember] public string Nome{ get { return _nome; } set { _nome = value; } } [DataMember] private string Cognome{ get { return _cognome; } set { _cognome = value; } } public string CodiceFiscale{ get { return _codicefiscale; } set { _codicefiscale = value; } } }
Possono essere definite anche altre proprietà come l’ordine, l’obbligatorietà di un dato e altro ancora.