Creazione e pubblicazione di un web service
in Visual Studio 2005
Corso di Informatica industriale
Prof. Ing. Salvatore Cavalieri
Ing. Giovanni Cutuli
I web service
Il web service è un sistema software
progettato per supportare il concetto di
interoperabilità fra diversi host all'interno di
una rete
 L' interfaccia è definita utilizzando WSDL
 La comunicazione avviene mediante SOAP
 I messaggi sono trasportati dal protocollo
HTTP
 I messaggi sono formattati in XML

XML
L'HTML è un linguaggio creato principalmente per la descrizione e
la formattazione di pagine web mentre XML è un metalinguaggio
utilizzato per creare nuovi linguaggi, atti a descrivere
documenti strutturati.
In HTML si hanno un insieme già definito di tag utilizzabili per la
creazione delle pagine, mentre in XML è invece possibile definirne
di propri a seconda delle esigenze.
<?xml version="1.0" ?>
<utenti>
<utente>
<nome>Mario</nome>
<cognome>Rossi</cognome>
</utente>
<utente>
<nome>Max</nome>
<cognome>Verdi</cognome>
</utente>
</utenti>
Creazione di un servizio Web
• Passo 1: Creazione nuovo progetto in VS 2005
• Passo 2: Creazione di un servizio ASP. NET
Creazione di un servizio Web
• Passo 3: Esempio automatico “HelloWorld” nel file Service.asmx
Creazione di un servizio Web
• Passo 4: Avviare il debug del servizio web
• Passo 5: Creazione file di configurazione del servizio Web
Creazione di un servizio Web
• Passo 6: Avvio del server di sviluppo integrato ASP.NET
• Passo 7: Test del servizio Web
Creazione di un servizio Web
• Passo 8: Richiamare un servizio pubblicato dal web service
• Passo 9: Risultato della chiamata al web service
Il file WSDL
La descrizione dei servizi esportati dal web
service è fatta in WSDL ed inserita in un
opportuno file che avrà estensione “wsdl”. E’
possibile prendere visione del file aggiungendo
la stringa “?WSDL” alla fine dell’ URL del web
service.

Esempio:
Se l’URL del web service è:
http://localhost:1139/WebService/Service.asmx
Allora la relativa descrizione dei servizi si otterrà col seguente URL
http://localhost:1139/WebService/Service.asmx?WSDL

Il file WSDL
Pubblicazione del servizio
Per pubblicare il servizio Web dopo averlo sviluppato e testato è
necessario farlo riconoscere ad IIS. Con la seguente procedura si
pubblicherà il servizio Web in modo che non utilizzi più il server di
sviluppo ASP.NET bensì IIS.
• Passo 1: Predisporre una directory sotto C:\Inetpub\wwwroot di
nome “prova_sito” dove andranno posizionati i file necessari per il
corretto funzionamento del servizio web. Dopo aver creato la cartella
bisogna modificare i permessi sulla cartella appena creata altrimenti
il servizio web non potrà funzionare ed ovviamente avviare IIS sull’
indirizzo localhost.
Pubblicazione del servizio
Pubblicazione del servizio
Pubblicazione del servizio
Per pubblicare il servizio Web dopo averlo sviluppato e testato è
necessario farlo riconoscere ad IIS. Con la seguente procedura si
pubblicherà il servizio Web in modo che non utilizzi più il server di
sviluppo ASP.NET bensì IIS.
• Passo 2: Utilizzare la procedura guidata
Pubblicazione del servizio
• Passo 3: Configurare il servizio web
• Passo 4: Testare il servizio web
http://indirizzoIP/prova_sito/Service.asmx
Pubblicazione del servizio
• Problemi di funzionamento:
Se si riscontrano problemi di funzionamento dovuto ad errori sul file di
configurazione (.config) molto probabilmente non si sta utilizzando la
versione corretta del framework .NET. E’ necessario quindi selezionare
quella corretta col seguente comando lanciato dal prompt:
C:\Windows\Microsoft.NET\Framework\v2.0.50215\aspnet_regiis.exe –i
E dopo riavviare Internet Information Service col comando iisreset
Creazione di un client
• Passo 1: Creazione di un nuovo progetto in
Visual Studio 2005
Creazione di un client
• Passo 2: Creazione di una console application
Creazione di un client
• Passo 3: E’ necessario aggiungere un
riferimento Web nel progetto per permettere al
client di dialogare col servizio web
precedentemente creato.
Creazione di un client
• Passo 4: Cercare il servizio fra i servizi locali
Creazione di un client
• Passo 5: Selezionare il servizio desiderato
Creazione di un client
• Passo 6: aggiungere il riferimento al progetto
rinominandolo come “Servizio”.
Se dovessero
esserci problemi
controllare
l’indirizzo del server
Creazione di un client
• Il riferimento appena inserito dovrà apparire
fra i file coinvolti nel progetto.
Creazione di un client
• Passo 7: Creazione di un oggetto che
rappresenta il servizio web. A questo punto è
possibile invocare tutti i metodi del servizio web
come se fossero locali.
La parola chiave out in C#
In C# con la parola chiave out gli argomenti saranno passati per
riferimento. Funzionalità simile offre la parola chiave ref, solo che se si
sceglie di utilizzare ref la variabile passata alla funzione deve essere
prima inizializzata.
Per utilizzare un parametro out, è necessario che la definizione del
metodo e il metodo chiamante utilizzino in modo esplicito la parola
chiave out.
Esempio
Esempio
Funzioni e strutture dati in OPC XML-DA
Corso di Informatica industriale
Prof. Ing. Salvatore Cavalieri
Ing. Giovanni Cutuli
OPC XML DA
Per lo scambio dati fra client e server sono
previste determinate strutture dati che
servono ad inglobare al loro interno le varie
informazioni da inviare al web service e di
conseguenza le informazioni di risposta che il
web service invia al client.

Esempio di scambio dati
(GetStatus)
Server OPC XML-DA
Client OPC XML-DA
GetStatus
(string LocaleID, string ClientRequestHandle, out ServerStatus Status)
GetStatusResponse
(ReplyBase Response, ServerStatus Status)





DateTime rcvTimeField;
DateTime replyTimeField;
string clientRequestHandleField;
string revisedLocaleIDField;
serverState serverStateField;






string statusInfoField;
string vendorInfoField;
string[] supportedLocaleIDsField;
interfaceVersion[] supportedInterfaceVersionsField;
DateTime startTimeField;
string productVersionField
Esempio di scambio dati (Read)
Server OPC XML-DA
Client OPC XML-DA
Read
(RequestOptions Options, ReadRequestItemList ItemList, out ReplyItemList
RItemList, out OPCError[] Errors)
ReadResponse
(ReplyBase ReadResult, ReplyItemList RItemList, OPCError[] Errors)
 boolean
 boolean
 boolean
 boolean
…
ReturnErrorText
ReturnDiagnosticInfo
ReturnItemTime
ReturnItempath
 string ItemPath
QName ReqType
int MaxAge
ReadRequestItem[] Items
Esempio di scambio dati (Write)
Server OPC XML-DA
Client OPC XML-DA
Write
(RequestOptions Options, WriteRequestItemList ItemList, bool
ReturnValuesOnReply, out ReplyItemList RItemList, out OPCError[] Errors)
WriteResponse
(ReplyBase WriteResult, ReplyItemList RItemList, OPCError[] Errors)
 boolean
 boolean
 boolean
 boolean
…
ReturnErrorText
ReturnDiagnosticInfo
ReturnItemTime
ReturnItempath
ItemValue[] Items
Esempio di scambio dati
(Subscribe)
Server OPC XML-DA
Client OPC XML-DA
Subscribe
(RequestOptions Options, SubscribeRequestItemList ItemList, bool
ReturnValuesOnReply, int SubscriptionPingRate, out SubscribeReplyItemList
RItemList, out OPCError[] Errors, out string ServerSubHandle)
SubscribeResponse
(ReplyBase SubscribeResult, SubscribeReplyItemList RItemList, OPCError[]
Errors, string ServerSubHandle)
 SubscribeRequestItem[] Items
Esempio di scambio dati
(Subscription Polled Refresh)
Server OPC XML-DA
Client OPC XML-DA
SubscriptionPolledRefresh
(RequestOptions Options, string[] ServerSubHandles, System.DateTime HoldTime,
bool HoldTimeSpecified, int WaitTime, bool ReturnAllItems, out string[]
InvalidServerSubHandles, out SubscribePolledRefreshReplyItemList[] RItemList, out
OPCError[] Errors, out bool DataBufferOverflow)
SubscriptionPolledRefreshResponse
(ReplyBase SubscriptionPolledRefresh Result, string[]
InvalidServerSubHandles, SubscribePolledRefreshReplyItemList[] RItemList,
OPCError[] Errors, bool DataBufferOverflow)
Esempio di scambio dati
(Subscription Cancel)
Server OPC XML-DA
Client OPC XML-DA
SubscriptionCancel
(string ServerSubHandle, ref string ClientRequestHandle)
SubscriptionCancel Response
(string ClientRequestHandle)
Esempio di scambio dati
(Browse)
Server OPC XML-DA
Client OPC XML-DA
Browse
(System.Xml.XmlQualifiedName[] PropertyNames, string LocaleID, string
ClientRequestHandle, string ItemPath, string ItemName, ref string ContinuationPoint, int
MaxElementsReturned, browseFilter BrowseFilter, string ElementNameFilter, string
VendorFilter, bool ReturnAllProperties, bool ReturnPropertyValues, bool ReturnErrorText,
out BrowseElement[] Elements, out OPCError[] Errors, out bool MoreElements)
BrowseResponse
(ReplyBase BrowseResult, BrowseElement[] Elements, OPCError[] Errors, bool
MoreElements)
 Enumeration {all, branch, item}





string ItemPath
string ItemName
bool IsItem
bool HasChildren
ItemProperty[] Properties
Esempio di scambio dati
(Get Properties)
Server OPC XML-DA
Client OPC XML-DA
GetProperties
(ItemIdentifier[] ItemIDs, System.Xml.XmlQualifiedName[] PropertyNames, string
LocaleID, string ClientRequestHandle, string ItemPath, bool ReturnAllProperties,
bool ReturnPropertyValues, bool ReturnErrorText, out PropertyReplyList[]
PropertyLists, out OPCError[] Errors)
GetProperties Response
(ReplyBase GetProperties Result, PropertyReplyList[] PropertyLists, OPCError[] Errors)
 ItemProperty[] Properties
 string Description
 string ItemPath
 string ItemName
 …
WSDL per GetStatus
<s:element name="GetStatus">
<s:complexType>
<s:attribute name="LocaleID" type="s:string" />
<s:attribute name="ClientRequestHandle" type="s:string" />
</s:complexType>
</s:element>
<s:element name="GetStatusResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetStatusResult" type="s0:ReplyBase" />
<s:element minOccurs="0" maxOccurs="1" name="Status" type="s0:ServerStatus" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ReplyBase">
<s:attribute name="RcvTime" type="s:dateTime" use="required" />
<s:attribute name="ReplyTime" type="s:dateTime" use="required" />
<s:attribute name="ClientRequestHandle" type="s:string" />
<s:attribute name="RevisedLocaleID" type="s:string" />
<s:attribute name="ServerState" type="s0:serverState" use="required" />
</s:complexType>
Il file WSDL ufficiale di OPC XML-DA
Corso di Informatica industriale
Prof. Ing. Salvatore Cavalieri
Ing. Giovanni Cutuli
Compilatore WSDL
Per compilare il file WSDL ufficiale di
OPC foundation è necessario un tool
presente in Visual Studio 2005. Il tool in
questione è il compilatore WSDL
invocabile col comando “wsdl”.
 Il comando WSDL è visibile, per
impostazione predefinita, soltanto dal
prompt dei comandi di Visual Studio.

Compilatore WSDL
Basta lanciare il comando wsdl senza
parametri per ottenere l’ elenco delle opzioni
disponibili. La forma generale di utilizzo del
compilatore è la seguente:

In cui:
 <opzioni>: rappresenta l’insieme di opzioni di
compilazione
 <url o percorso>: indica il percorso del file
WSDL da compilare
Compilatore WSDL
Le opzioni più importanti, che saranno usate in
seguito, sono:
“/language: <linguaggio>” opzione che serve a
specificare in che linguaggio creare la classe
(default: c#)
“/namespace: <spaziodeinomi>” opzione che serve
a definire lo spazio dei nomi
“/out:<nomefile>” opzione che serve a definire un
nome per il file di output generato alla fine della
compilazione (il nome della classe è Service)
Creazione OPC Client
 Passo 1: Creazione classe proxy del client che
conterrà tutti i metodi, strutture dati e tutto il
necessario per una buona programmazione e un
buon funzionamento del client OPC
WSDL file
Compilatore WSDL
Classe “proxy” client
 Il comando da lanciare per ottenere la classe
proxy client in C# (di nome Service) e
memorizzarla nel file ClientProxy.cs è il seguente:
wsdl /language:cs /out:ClientProxy.cs OPC.wsdl
Creazione OPC Client
 Quello che si ottiene è una classe definita cosi:
public partial class Service : System.Web.Services.Protocols.SoapHttpClientProtocol
{
//codice del client
}
La parola chiave partial in C# consente di definire
classi, metodi e strutture dati in generale all’interno
di diversi file che verranno “unificati” in fase di
compilazione.
Creazione OPC Client
 Passo 2: Creare una console application in
Visual Studio 2005 per poter costruire il client OPC
Creazione OPC Client
 Passo 3: Aggiungere i riferimenti a System.Web
e System.Web.Services
 Passo 4: Aggiungere al progetto il file
ClientProxy.cs
Creazione OPC Client
 Passo 5 (opzionale): Includere la classe
ProxyClient al namespace del progetto
namespace ConsoleApplication
{
//ProxyClient code
}
In questo modo la classe ProxyClient farà parte
dello stesso spazio dei nomi del programma
principale (main) che rappresenta il client OPC
Creazione OPC Client
 Passo 6: Sviluppare il client OPC. Prima cosa da
fare instanziare un oggetto che rappresenta il
server OPC con il quale dialogare definendo l’ URL
al quale si trova.
Creazione OPC Client (GetStatus)
 Passo 7: Sviluppare i vari metodi del client OPC.
Stampa dei risultati (GetStatus)
Creazione OPC Client (Read)
 La Read che utilizzeremo più avanti ha la
seguente firma:
 Prima è necessario definire le strutture dati
necessarie:
Creazione OPC Client (Read)
Creazione OPC Client (Read)
Stampa dei risultati (Read)
 Chiamata al metodo e stampa dei risultati
Stampa dei risultati (Read)
 Chiamata al metodo e stampa dei risultati
Creazione OPC Client (Write)
 La Write che utilizzeremo più avanti ha la
seguente firma:
 Prima è necessario definire le strutture dati
necessarie non definite prima:
Creazione OPC Client (Write)
Stampa dei risultati (Write)
 Chiamata al metodo e stampa dei risultati
Stampa dei risultati (Write)
Creazione OPC Client (Subscribe)
 La Subscribe che utilizzeremo più avanti ha la
seguente firma:
 Prima è necessario definire le strutture dati
necessarie non definite prima:
Stampa dei risultati (Subscribe)
 Stampa dei risultati
Creazione OPC Client
(SubscriptionPolledRefresh)
 La SubscriptionPolledRefresh che utilizzeremo
più avanti ha la seguente firma:
 Prima è necessario definire le strutture dati
necessarie non definite prima:
Stampa dei risultati
(SubscriptionPolledRefresh)
 Stampa dei risultati
Creazione OPC Client
(SubscriptionCancel)
 La SubscriptionCancel che utilizzeremo più
avanti ha la seguente firma:
Creazione OPC Client (Browse)
 La Browse che utilizzeremo più avanti ha la
seguente firma:
 Prima è necessario definire le strutture dati
necessarie non definite prima:
Stampa dei risultati (Browse)
 Stampa dei risultati
Creazione OPC Client
(GetProperties)
 La GetProperties che utilizzeremo più avanti ha
la seguente firma:
 Prima è necessario definire le strutture dati
necessarie non definite prima:
Stampa dei risultati (GetProperties)
 Stampa dei risultati
Connessione ad un server OPC XML
Corso di Informatica industriale
A.A. 2007 - 2008
Prof. Ing. Salvatore Cavalieri
Ing. Giovanni Cutuli
Parametri connessione
Supponiamo che l’ IP del
server sia 192.168.0.9
Attivare l’opzione “Ottieni
automaticamente un
indirizzo IP”, in modo da
ottenere un indirizzo in
modo automatico. Se si
vuole impostare tutto
manualmente è sufficiente
inserire un indirizzo del tipo
192.168.0.x dove x ≠9
Parametri connessione
Nel codice del client sostituire l’URL del server con il
nuovo URL:
Invocare i metodi sul server e controllarne le
risposte (come visto in precedenza)
Creazione di un server OPC XML-DA
Corso di Informatica industriale
Prof. Ing. Salvatore Cavalieri
Ing. Giovanni Cutuli
Compilatore WSDL
Per compilare il file WSDL ufficiale di
OPC foundation per la classe lato server
si utilizza lo stesso tool utilizzato per
creare la classe proxy del client. Il tool in
questione è il compilatore “wsdl” al quale
si associano gli opportuni parametri.

Compilatore WSDL
Basta lanciare il comando wsdl senza
parametri per ottenere l’ elenco delle opzioni
disponibili. La forma generale di utilizzo del
compilatore è la seguente:

In cui:
 <opzioni>: rappresenta l’insieme di opzioni di
compilazione
 <url o percorso>: indica il percorso del file
WSDL da compilare
Compilatore WSDL
Le opzioni più importanti e che saranno usate in seguito
sono:
“/language: <linguaggio>” opzione che serve a
specificare in che linguaggio creare la classe astratta
(default: c#)
“/namespace: <spaziodeinomi>” opzione che serve a
definire lo spazio dei nomi
“/out:<nomefile>” opzione che serve a definire un nome
per il file di output generato alla fine della compilazione (il
nome della classe è Service)
“/server” opzione che serve a generare la classe
astratta per il server OPC (se l’opzione è omessa il
tool genera la classe proxy per il client)
Creazione OPC Server
 Passo 1: Creazione classe proxy del server che
conterrà tutti i metodi, strutture dati e tutto il
necessario per una buona programmazione e un
buon funzionamento del server OPC
WSDL file
Compilatore WSDL
Classe “proxy” server
 Il comando da lanciare per ottenere la classe
proxy client in C# (di nome Service) e
memorizzarla nel file ProxyServer.cs è il seguente:
wsdl /language:cs /out:ProxyServer.cs /server
OPC.wsdl
Creazione OPC Server
 Quello che si ottiene è una classe definita cosi:
public abstract partial class Service : System.Web.Services.WebService
{
//codice del server proxy
}
Utilizzare il modificatore abstract in una
dichiarazione di classe significa che una classe può
essere utilizzata soltanto come classe base di altre
classi. I membri contrassegnati come astratti o
inclusi in una classe astratta devono essere
implementati da classi che derivano dalla classe
astratta.
Creazione OPC Server
 Passo 2: Creare un nuovo progetto in Visual Studio 2005. Il progetto
deve essere di tipo Web ed in particolare dovrà essere un servizio Web
ASP.NET
Creazione OPC Server
 Passo 3: Aggiungere il file ProxyServer.cs al
progetto appena creato.
Creazione OPC Server
 Passo 4: Da Visual Studio trascinare il file
ProxyServer.cs all’interno della cartella APP_CODE
del progetto.
Creazione OPC Server
 Rinominare il file Service.cs in
ServerOPC.cs per evitare
confusione con la classe Service
presente all’ interno del file
ProxyServer.cs che rappresenta
invece la classe astratta del
servizio web
Creazione OPC Server
 Rinominare il file Service.asmx in
ServerOPC.asmx e modificarne il contenuto
Creazione OPC Server
 I file principali del progetto sono:
 ProxyServer.cs : classe proxy del server.
ServerOPC.asmx : classe principale del servizio
Web (e quindi del server OPC). Il suo codice è
racchiuso in ServerOPC.cs
Per contattare il server (dopo la pubblicazione) si
utilizzerà il seguente link:
http://ip/ProvaServerOPC/ServerOPC.asmx
Creazione OPC Server
 Passo 5: Fare in modo che la classe ServerOPC
(definita in ServerOPC.cs) estenda la classe
Service definita all’interno del file ProxyServer.cs e
non System.Web.Services.Webservice
public class ServerOPC : Service
{
//OPC Server code
}
In questo modo la classe Server estenderà la
classe astratta Service contenuta in ProxyServer.cs
Creazione OPC Server
 Dal punto di vista concettuale è stata appena
creata la seguente architettura:
WSDL OPC
Compilazione
Classe proxy del server OPC
(di nome Service ed
estende System.Web.Services.WebService)
Classe del server OPC
(di nome ServerOPC ed
estende la classe Service)
Client OPC
Connessione
Creazione OPC Server
 Passo 6: Sviluppare il server OPC
implementando tutti i metodi che ci impone la
classe astratta Service (altrimenti non compila).
Creazione OPC Server
 Quando si implementa un metodo che era
definito come abstract in c# bisogna anteporre la
parola chiave override
Creazione OPC Server
 Implementare i metodi non basta, soprattutto
se nei parametri della funzione sono presenti
parametri out. Esempio con GetStatus:
 In tal caso basta sviluppare la funzione in modo
che ritorni i parametri richiesti, anche se vuoti:
public override ReplyBase GetStatus(…) {
Status = null;
ReplyBase Response = new ReplyBase();
return Response;
}
Creazione OPC Server
 Se non si mettesse la linea:
Status = null;
il compilatore darebbe errore:
perché tutti i parametri out devono essere
assegnati prima che la chiamata a funzione termini
Creazione OPC Server
 Passo 7: Impostare come pagina iniziale del
progetto il file contenente il server OPC
Creazione OPC Server
 Passo 8: Avviare e testare il server OPC
Potrebbe essere necessario aggiungere un nuovo
file Web.config (come visto in precedenza)
Creazione OPC Server
 Avviando il server appare l’interfaccia con i
metodi esportati dal server:
Pubblicazione del server OPC
A questo punto il nostro servizio web ha bisogno
solo di essere pubblicato, predisponendo una
cartella dal nome ProvaServerOPC (utilizzando la
procedura vista in precedenza).
Dopo la pubblicazione del servizio, il server OPC
sarà disponibile all’ indirizzo:
http://ip/ProvaServerOPC/ServerOPC.asmx
Esempio GetStatus lato server
public override ReplyBase GetStatus(string LocaleID, ClientRequestHandle, out ServerStatus status)
{
ReplyBase Response = new ReplyBase();
Response.RcvTime = System.DateTime.Now;
Response.ServerState = serverState.running;
Response.ClientRequestHandle = "Client Handle modificato dal server";
Response.RevisedLocaleID = "IT";
Status = new ServerStatus();
Status.ProductVersion = "Product version";
Status.StartTime = new DateTime(2008, 06, 04, 11, 0, 0);
Status.StatusInfo = "Status info";
Status.SupportedInterfaceVersions = new interfaceVersion[1];
Status.SupportedInterfaceVersions[0] = interfaceVersion.XML_DA_Version_1_0;
Status.SupportedLocaleIDs = new string[1];
Status.SupportedLocaleIDs[0] = "IT";
Status.VendorInfo = "Vendor INFO";
}
Response.ReplyTime = System.DateTime.Now;
return Response;
Salvataggio variabili
Corso di Informatica industriale
Prof. Ing. Salvatore Cavalieri
Ing. Giovanni Cutuli
Salvare le variabili
Supponiamo di voler memorizzare quante volte è
stata attivata una determinata funzione, da
quando il servizio è in run. Ovviamente tale valore
andrebbe perso se il servizio dovesse smettere di
funzionare e dovesse essere necessario il riavvio
dei servizi.
CLIENT
Attivazione della funzione
SERVER
callCounterVariable
Salvare le variabili
 Creare un semplice Web Service come visto in
precedenza.
Salvare le variabili
 Click destro sul nome del progetto e aggiungere
una “classe di applicazione globale”
Salvare le variabili
 A questo punto il contenuto del progetto sarà:
Salvare le variabili
Salvare le variabili
 Caso senza salvataggio variabili
Salvare le variabili
Salvare le variabili
Salvare le variabili
 Caso con salvataggio variabili (Global.asax)
Salvare le variabili
 Caso con salvataggio variabili (Service.cs)
Salvare le variabili
Salvare le variabili
Arrestiamo e avviamo nuovamente IIS e vediamo
cosa accade se richiamiamo la funzione
Salvare le variabili
Il conteggio riprende da zero dato che l’applicazione è stata riavviata
Salvare le variabili
E’ possibile memorizzare una variabile di livello applicativo direttamente nella
classe del servizio (nel file Service.cs), a patto che sia inizializzata.
Scarica

Realizzazione di un Client/Server OPC XML DA in C