Autore: Fabio Cozzolino
I servizi creati con Windows Communication Foundation (WCF), grazie alla sua architettura, possono essere messi in hosting su diversi tipi di applicazione, in base alle specifiche esigenze. Se vogliamo, infatti, ottenere qualcosa di simile ai classici servizi asmx, possiamo utilizzare come hosting IIS creando una semplice applicazione ASP.NET. Se, tuttavia, non vogliamo o non possiamo utilizzare un web server, allora possiamo utilizzare applicazioni Windows Forms, Console o Windows Service per creare degli hosting di servizi WCF. Proprio i Windows Service sono oggetto di questo articolo, nel quale vedremo come creare un servizio windows che espone servizi applicativi tramite WCF, ricreando una situazione del tutto simile a quella di un web server come IIS.
CREAZIONE DEL CONTRATTO
Prima di procedere con l’implementazione del servizio, è necessario stabilire quali sono le informazioni scambiate ed in che modo saranno esposte i consumer. Creiamo innanzitutto una soluzione di tipo Blank Solution ed aggiungiamo un progetto WinFx Service Library. Nel progetto andremo a definire una classe che espone sia il servizio windows sia il servizio WCF, ma prima dobbiamo definire il contratto come interfaccia. In linea con gli esempi trattati durante le sessioni del workshop Workflow & Communication Foundation realizzeremo un servizio in grado di restituire info dettagliate su un libro che stiamo cercando. il contratto potrebbe essere espresso attraverso l’interfaccia IBookSearch così implementata:
[ServiceContract(Namespace = "http://www.dotnetside.org/2006/06/BookSearch")]
public interface IBookSearch
{
[OperationContract()]
BookInfo FindByName(string bookName);
}
Decorando l’interfaccia IBookSearch con l’attributo ServiceContract, ed il metodo FindByName con l’attributo OperationContract stiamo comunicando al runtime WCF che l’interfaccia definisce un contratto di servizio e che i metodi esposti sono quelli da noi indicati.
DEFINIZIONE DEL SERVIZIO
Dopo la definizione dell’interfaccia, dobbiamo ora implementare il servizio e sfruttare l’architettura dei servizi windows per fornire l’hosting su cui poi ci appoggiamo. Iniziamo con l’aggiungere i riferimenti agli assembly necessari:
-
System.ServiceModel: l’assembly di base per la creazione di servizi WCF. Si trova nella cartella c:\WINDOWS\WinFX\v3.0\Windows Communication Foundation;
-
System.ServiceProcess: è l’assembly incluso nel .NET framework che contiene le classi base per la creazione di servizi windows;
-
La nostra classe deve ereditare dalla classe astratta System.ServiceProcess.ServiceBase ma contemporaneamente deve implementare l’interfaccia IBookSearch per realizzare il servizio WCF. Aggiungiamo, quindi, al nostro progetto un nuovo elemento Windows Service e lo chiamiamo BookWinService.cs. Modifichiamo la classe inserendo il seguente codice:
partial class BookWinService : ServiceBase, IBookSearch
{
ServiceHost host;
public BookWinService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
host = new ServiceHost(typeof(BookWinService));
host.AddServiceEndpoint(typeof(IBookSearch), new NetTcpBinding(), "net.tcp://localhost:9001/BookService");
host.Open();
}
protected override void OnStop()
{
host.Close();
}
#region IBookSearch Members
public BookInfo FindByName(string bookName)
{
Books books = new Books();
books.Populate();
return books.FindByName(bookName);
}
#endregion
}
come anticipato, la classe BookWinSearch eredita dalla classe base ServiceBase e contemporaneamente implementa l’interfaccia IBookSearch. Nell’evento Start crea l’instanza dell’hosting definendo un endpoint composto dal contratto IBookSearch, dal tipo di binding NetTcpBinding() e un address in ascolto sulla porta 9001. Infine apre l’hosting per metterlo in ascolto. Seguendo questi pochi, semplici passi abbiamo creato un servizio windows in grado di esporre un servizio WCF.
INSTALLAZIONE DEL SERVIZIO WINDOWS
L’installazione del servizio windows non è per nulla differente alla procedura normale. Ci posizioniamo nel designer del file BookWinService.cs e clicchiamo con il tasto destro del mouse. Nel menu contestuale apparirà la voce Add Installer che, una volta cliccata, aggiungerà al progetto una nuova classe che eredita da Installer contenente due componenti ServiceInstaller e ServiceProcessInstaller. Qui è possibile definire alcune proprietà per identificare e meglio definire il servizio windows. Posizioniamoci sul designer del ProjectInstaller e nelle proprietà del componente serviceInstaller1 impostiamo:
Nella property windows del componente processInstaller1 impostiamo, invece, le seguenti proprietà:
-
(Name) = process
-
Account = NetworkService
In questo modo impostiamo l’account NetworkService come l’account sotto il quale deve girare il processo simulando, quindi, una situazione del tutto simile a quella di un web server IIS dove, per impostazione predefinita, i processi ASP.NET vengono eseguiti con l’account NetworkService.
Dopo aver effettuato correttamente tutte le impostazioni, possiamo ora compilare il progetto. Se la compilazione va a buon fine proviamo ad installare il nostro servizio windows utilizzando l’utility da riga di comando installutil.exe con questi parametri:
installutil.exe <nome assembly>
se l’installazione non restituisce alcun errore allora vedremo il nostro servizio in funzione tra i servizi windows.

CREAZIONE DEL CLIENT
Il codice per la creazione del client utilizza la classe ChannelFactory per creare un canale di comunicazione con il servizio sulla base delle impostazioni riportate nel file di configurazione, nella sezione BookSearchEndpointConfig:
// creo il channel
ChannelFactory<DotNetSide.WinFx.EnterpriseService.Library.IBookSearch> channel = new
ChannelFactory<DotNetSide.WinFx.EnterpriseService.Library.IBookSearch>("BookSearchEndpointConfig");
// creo il proxy
DotNetSide.WinFx.EnterpriseService.Library.IBookSearch proxy = channel.CreateChannel();
// eseguo il servizio
DotNetSide.WinFx.EnterpriseService.Library.BookInfo book = proxy.FindByName(this.txtBookName.Text);
Provando ad eseguire l’applicazione client, il cui codice complete è allegato all’articolo, otterremo un risultato simile a questo:

CONCLUSIONI
Abbiamo visto come è relativamente semplice unire l’infrastruttura di servizi fornita da WinFx attraverso WCF con l’infrastruttura dei servizi windows. Nell’articolo abbiamo realizzato un semplice servizio WCF che espone le sue funzionalità attraverso un windows service, ricreando uno scenario molto simile a quello fornito da IIS, ma con in più il vantaggio di poter utilizzare, almeno fino all’uscita di WAS (Windows Activation Services), protocolli differenti dall’http. Nell’allegato all’articolo potete trovare l’applicazione di esempio completa. Good coding.
Riferimenti
Windows Communication Foundation – http://www.windowscommunication.net
WinFx – http://msdn.microsoft.com/winfx