Cenni preliminari sulla creazione di endpoint
Tutte le comunicazioni con un servizio Windows Communication Foundation (WCF) vengono eseguite tramite gli endpoint del servizio. Gli endpoint forniscono ai client l'accesso alla funzionalità offerta da un servizio WCF. Questa sezione descrive la struttura di un endpoint e viene illustrato come definire un endpoint nella configurazione e nel codice.
Struttura di un endpoint
Ogni endpoint contiene un indirizzo che indica dove individuare l'endpoint, un'associazione che specifica in che modo un client può comunicare con l'endpoint e un contratto che identifica i metodi disponibili.
Indirizzo. L'indirizzo identifica in modo univoco l'endpoint e comunica ai potenziali utenti l'ubicazione del servizio. È rappresentato nel modello a oggetti WCF dall'indirizzo EndpointAddress che contiene un URI (Uniform Resource Identifier) e proprietà dell'indirizzo che includono un'identità, alcuni elementi WSDL (Web Services Description Language) e una raccolta di intestazioni facoltative. Le intestazioni facoltative forniscono dettagli aggiuntivi sull'indirizzo per identificare o interagire con l'endpoint. Per altre informazioni, vedere Specifica di un indirizzo endpoint.
Binding. L'associazione specifica la modalità di comunicazione con l'endpoint. L'associazione specifica in che modo l'endpoint comunica con il mondo, incluso il protocollo di trasporto da usare (ad esempio, TCP o HTTP), il tipo di codifica da usare per i messaggi (ad esempio, testo o binaria) e i requisiti di sicurezza necessari (ad esempio, Secure Sockets Layer [SSL] o sicurezza dei messaggi SOAP). Per altre informazioni, vedere Uso di binding per configurare servizi e client.
Contratto di servizio. Il contratto di servizio delinea la funzionalità che l'endpoint espone al client. Un contratto specifica le operazioni che un client può richiamare, il modulo del messaggio e il tipo di parametri o dati di input necessari per chiamare l'operazione e il tipo di elaborazione o messaggio di risposta che il client può aspettarsi. Tre tipi di contratti di base corrispondono a modelli di scambio dei messaggi (MEP, Message Exchange Pattern) di base: datagramma (unidirezionale), request/reply e duplex (bidirezionale). Il contratto di servizio può inoltre usare contratti dati e contratti di messaggio per richiedere tipi di dati e formati di messaggio specifici al momento dell'accesso. Per altre informazioni su come definire un contratto di servizio, vedere Progettazione di contratti di servizio. Per ricevere messaggi dal servizio in un modello di scambio dei messaggi (MEP) duplex, è possibile che un client debba implementare un contratto definito dal servizio, detto contratto di callback. Per altre informazioni, vedere Servizi duplex.
L'endpoint per un servizio può essere specificato in modo imperativo mediante l'uso di codice oppure in modo dichiarativo mediante la configurazione. Se non è specificato alcun endpoint, il runtime ne fornisce di predefiniti aggiungendone uno per ogni indirizzo di base per ciascun contratto di servizio implementato dal servizio. In genere definire endpoint nel codice non è pratico in quanto le associazioni e gli indirizzi di un servizio distribuito sono solitamente diversi da quelli usati durante lo sviluppo del servizio. In genere è più pratico definire endpoint di servizio mediante la configurazione piuttosto che mediante codice. Se le informazioni sull'associazione e sull'indirizzo non vengono incluse nel codice, tali dati possono essere modificati senza dover compilare e distribuire nuovamente l'applicazione.
Nota
Quando si aggiunge un endpoint di servizio che esegue la rappresentazione, è necessario usare uno dei metodi AddServiceEndpoint o il metodo GetContract(Type, Type) per caricare correttamente il contratto in un nuovo oggetto ServiceDescription.
Definizione di endpoint nel codice
Nell'esempio riportato di seguito viene illustrato come specificare un endpoint nel codice.
Definire un contratto per un tipo di servizio
IEcho
che accetta il nome e l'eco di un utente con la risposta "Hello <name>!".Implementare un servizio
Echo
del tipo definito dal contrattoIEcho
.Specificare un indirizzo endpoint di
http://localhost:8000/Echo
per il servizio.Configurare il servizio
Echo
usando un'associazione WSHttpBinding.
namespace Echo
{
// Define the contract for the IEcho service
[ServiceContract]
public interface IEcho
{
[OperationContract]
String Hello(string name)
}
// Create an Echo service that implements IEcho contract
class Echo : IEcho
{
public string Hello(string name)
{
return "Hello" + name + "!";
}
public static void Main ()
{
//Specify the base address for Echo service.
Uri echoUri = new Uri("http://localhost:8000/");
//Create a ServiceHost for the Echo service.
ServiceHost serviceHost = new ServiceHost(typeof(Echo),echoUri);
// Use a predefined WSHttpBinding to configure the service.
WSHttpBinding binding = new WSHttpBinding();
// Add the endpoint for this service to the service host.
serviceHost.AddServiceEndpoint(
typeof(IEcho),
binding,
echoUri
);
// Open the service host to run it.
serviceHost.Open();
}
}
}
' Define the contract for the IEcho service
<ServiceContract()> _
Public Interface IEcho
<OperationContract()> _
Function Hello(ByVal name As String) As String
End Interface
' Create an Echo service that implements IEcho contract
Public Class Echo
Implements IEcho
Public Function Hello(ByVal name As String) As String _
Implements ICalculator.Hello
Dim result As String = "Hello" + name + "!"
Return result
End Function
' Specify the base address for Echo service.
Dim echoUri As Uri = New Uri("http://localhost:8000/")
' Create a ServiceHost for the Echo service.
Dim svcHost As ServiceHost = New ServiceHost(GetType(HelloWorld), echoUri)
' Use a predefined WSHttpBinding to configure the service.
Dim binding As New WSHttpBinding()
' Add the endpoint for this service to the service host.
serviceHost.AddServiceEndpoint(GetType(IEcho), binding, echoUri)
' Open the service host to run it.
serviceHost.Open()
Nota
L'host del servizio viene creato con un indirizzo di base. Il resto dell'indirizzo, relativo all'indirizzo di base, viene quindi specificato come parte di un endpoint. Questo partizionamento dell'indirizzo consente a più endpoint di essere definiti in modo più appropriato per i servizi presenti in un host.
Nota
Le proprietà di ServiceDescription nell'applicazione del servizio non devono essere modificate dopo la chiamata al metodo OnOpening su ServiceHostBase. Se vengono modificati dopo questo punto, alcuni membri, ad esempio la proprietà Credentials e i metodi AddServiceEndpoint
su ServiceHostBase e ServiceHost, generano un'eccezione. Altri consentono la modifica, ma il risultato è indefinito.
Analogamente, sul client i valori ServiceEndpoint non devono essere modificati dopo la chiamata a OnOpening su ChannelFactory. Se viene modificata dopo questo punto, la proprietà Credentials genera un'eccezione. Gli altri valori della descrizione client possono essere modificati senza errore, ma il risultato è indefinito.
Per il servizio o per il client, è consigliabile modificare la descrizione prima di chiamare Open.
Definizione di endpoint nella configurazione
Durante la creazione di un'applicazione è spesso necessario rimettere le decisioni all'amministratore che distribuisce l'applicazione. Spesso non è possibile prevedere, ad esempio, quale sarà l'indirizzo (URI) di un servizio. Anziché inserire un indirizzo nel codice, è preferibile consentire che questa operazione venga eseguita da un amministratore dopo la creazione del servizio. Questa flessibilità viene realizzata attraverso la configurazione. Per informazioni dettagliate, vedere Configurazione dei servizi.
Nota
Usare lo Strumento ServiceModel Metadata Utility (Svcutil.exe) con il passaggio /config:
nome file[,
nome file]
per creare rapidamente i file di configurazione.
Uso di endpoint predefiniti
Se non è specificato alcun endpoint nel codice o nella configurazione, il runtime ne fornisce di predefiniti aggiungendone uno per ogni indirizzo di base per ciascun contratto di servizio implementato dal servizio. L'indirizzo di base può essere specificato nel codice o nella configurazione e gli endpoint predefiniti vengono aggiunti quando viene chiamato Open() in ServiceHost. Questo esempio è identico a quello della sezione precedente, ma poiché non è stato specificato alcun endpoint, vengono aggiunti gli endpoint predefiniti.
namespace Echo
{
// Define the contract for the IEcho service
[ServiceContract]
public interface IEcho
{
[OperationContract]
String Hello(string name)
}
// Create an Echo service that implements IEcho contract
public class Echo : IEcho
{
public string Hello(string name)
{
return "Hello" + name + "!";
}
public static void Main ()
{
//Specify the base address for Echo service.
Uri echoUri = new Uri("http://localhost:8000/");
//Create a ServiceHost for the Echo service.
ServiceHost serviceHost = new ServiceHost(typeof(Echo),echoUri);
// Open the service host to run it. Default endpoints
// are added when the service is opened.
serviceHost.Open();
}
}
}
' Define the contract for the IEcho service
<ServiceContract()> _
Public Interface IEcho
<OperationContract()> _
Function Hello(ByVal name As String) As String
End Interface
' Create an Echo service that implements IEcho contract
Public Class Echo
Implements IEcho
Public Function Hello(ByVal name As String) As String _
Implements ICalculator.Hello
Dim result As String = "Hello" + name + "!"
Return result
End Function
' Specify the base address for Echo service.
Dim echoUri As Uri = New Uri("http://localhost:8000/")
' Open the service host to run it. Default endpoints
' are added when the service is opened.
serviceHost.Open()
Se vengono forniti endpoint in modo esplicito, è comunque possibile aggiungere gli endpoint predefiniti chiamando AddDefaultEndpoints su ServiceHost prima di chiamare Open. Per altre informazioni sugli endpoint predefiniti, vedere Configurazione semplificata e Configurazione semplificata per servizi WCF.