Procedure: Een dubbelzijdig contract maken
In dit onderwerp worden de basisstappen beschreven voor het maken van methoden die gebruikmaken van een dubbelzijdig (tweerichtingscontract). Met een dubbelzijdig contract kunnen clients en servers onafhankelijk van elkaar communiceren, zodat beide aanroepen naar de andere kunnen initiëren. Het duplex-contract is een van de drie berichtpatronen die beschikbaar zijn voor WCF-services (Windows Communication Foundation). De andere twee berichtpatronen zijn eenrichtings- en aanvraagantwoord. Een dubbelzijdig contract bestaat uit twee eenrichtingscontracten tussen de client en de server en vereist niet dat de methode-aanroepen worden gecorreleerd. Gebruik dit type contract wanneer uw service een query op de client moet uitvoeren voor meer informatie of expliciet gebeurtenissen op de client moet genereren. Voor meer informatie over het maken van een clienttoepassing voor een dubbelzijdig contract raadpleegt u Procedures: Toegang tot services met een duplex-contract. Zie het duplex-voorbeeld voor een werkend voorbeeld.
Een dubbelzijdig contract maken
Maak de interface waaruit de serverzijde van het duplex-contract bestaat.
Pas de ServiceContractAttribute klasse toe op de interface.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required, CallbackContract=typeof(ICalculatorDuplexCallback))] public interface ICalculatorDuplex { [OperationContract(IsOneWay=true)] void Clear(); [OperationContract(IsOneWay = true)] void AddTo(double n); [OperationContract(IsOneWay = true)] void SubtractFrom(double n); [OperationContract(IsOneWay = true)] void MultiplyBy(double n); [OperationContract(IsOneWay = true)] void DivideBy(double n); }
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required, _ CallbackContract:=GetType(ICalculatorDuplexCallback))> _ Public Interface ICalculatorDuplex <OperationContract(IsOneWay:=True)> _ Sub Clear() <OperationContract(IsOneWay:=True)> _ Sub AddTo(ByVal n As Double) <OperationContract(IsOneWay:=True)> _ Sub SubtractFrom(ByVal n As Double) <OperationContract(IsOneWay:=True)> _ Sub MultiplyBy(ByVal n As Double) <OperationContract(IsOneWay:=True)> _ Sub DivideBy(ByVal n As Double) End Interface
Declareer de methodehandtekeningen in de interface.
Pas de OperationContractAttribute klasse toe op elke methodehandtekening die deel moet uitmaken van het openbare contract.
Maak de callback-interface die de set bewerkingen definieert die de service op de client kan aanroepen.
public interface ICalculatorDuplexCallback { [OperationContract(IsOneWay = true)] void Equals(double result); [OperationContract(IsOneWay = true)] void Equation(string eqn); }
Public Interface ICalculatorDuplexCallback <OperationContract(IsOneWay:=True)> _ Sub Equals(ByVal result As Double) <OperationContract(IsOneWay:=True)> _ Sub Equation(ByVal eqn As String) end interface
Declareer de methodehandtekeningen in de callback-interface.
Pas de OperationContractAttribute klasse toe op elke methodehandtekening die deel moet uitmaken van het openbare contract.
Koppel de twee interfaces aan een dubbelzijdig contract door de CallbackContract eigenschap in de primaire interface in te stellen op het type callback-interface.
Methoden aanroepen op de client
Declareer in de implementatie van de service van het primaire contract een variabele voor de callback-interface.
Stel de variabele in op de objectverwijzing die wordt geretourneerd door de GetCallbackChannel methode van de OperationContext klasse.
ICalculatorDuplexCallback callback = null;
Dim callback As ICalculatorDuplexCallback
callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
Roep de methoden aan die zijn gedefinieerd door de callback-interface.
Opmerking
In het volgende codevoorbeeld ziet u duplexcommunicatie. Het contract van de service bevat servicebewerkingen voor vooruit en achteruit. Het contract van de klant bevat een servicebewerking voor het rapporteren van de positie.
// Define a duplex service contract.
// A duplex contract consists of two interfaces.
// The primary interface is used to send messages from client to service.
// The callback interface is used to send messages from service back to client.
// ICalculatorDuplex allows one to perform multiple operations on a running result.
// The result is sent back after each operation on the ICalculatorCallback interface.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
[OperationContract(IsOneWay=true)]
void Clear();
[OperationContract(IsOneWay = true)]
void AddTo(double n);
[OperationContract(IsOneWay = true)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true)]
void DivideBy(double n);
}
// The callback interface is used to send messages from service back to client.
// The Equals operation will return the current result after each operation.
// The Equation operation will return the complete equation after Clear() is called.
public interface ICalculatorDuplexCallback
{
[OperationContract(IsOneWay = true)]
void Equals(double result);
[OperationContract(IsOneWay = true)]
void Equation(string eqn);
}
// Service class which implements a duplex service contract.
// Use an InstanceContextMode of PerSession to store the result
// An instance of the service will be bound to each duplex session
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
double result;
string equation;
ICalculatorDuplexCallback callback = null;
public CalculatorService()
{
result = 0.0D;
equation = result.ToString();
callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
}
public void Clear()
{
callback.Equation(equation + " = " + result.ToString());
result = 0.0D;
equation = result.ToString();
}
public void AddTo(double n)
{
result += n;
equation += " + " + n.ToString();
callback.Equals(result);
}
public void SubtractFrom(double n)
{
result -= n;
equation += " - " + n.ToString();
callback.Equals(result);
}
public void MultiplyBy(double n)
{
result *= n;
equation += " * " + n.ToString();
callback.Equals(result);
}
public void DivideBy(double n)
{
result /= n;
equation += " / " + n.ToString();
callback.Equals(result);
}
}
' Define a duplex service contract.
' A duplex contract consists of two interfaces.
' The primary interface is used to send messages from client to service.
' The callback interface is used to send messages from service back to client.
' ICalculatorDuplex allows one to perform multiple operations on a running result.
' The result is sent back after each operation on the ICalculatorCallback interface.
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required, _
CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex
<OperationContract(IsOneWay:=True)> _
Sub Clear()
<OperationContract(IsOneWay:=True)> _
Sub AddTo(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub SubtractFrom(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub MultiplyBy(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub DivideBy(ByVal n As Double)
End Interface
' The callback interface is used to send messages from service back to client.
' The Equals operation will return the current result after each operation.
' The Equation operation will return the complete equation after Clear() is called.
Public Interface ICalculatorDuplexCallback
<OperationContract(IsOneWay:=True)> _
Sub Equals(ByVal result As Double)
<OperationContract(IsOneWay:=True)> _
Sub Equation(ByVal eqn As String)
end interface
' Service class which implements a duplex service contract.
' Use an InstanceContextMode of PerSession to store the result
' An instance of the service will be bound to each duplex session
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class CalculatorService
Implements ICalculatorDuplex
Dim result As Double
Dim equation As String
Dim callback As ICalculatorDuplexCallback
Public Sub New()
result = 0D
equation = result.ToString()
callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
End Sub
Public Sub AddTo(ByVal n As Double) Implements ICalculatorDuplex.AddTo
result += n
equation += " + " + n.ToString()
callback.Equals(result)
End Sub
Public Sub Clear() Implements ICalculatorDuplex.Clear
callback.Equation(equation + " = " + result.ToString())
result = 0D
equation = result.ToString()
End Sub
Public Sub DivideBy(ByVal n As Double) Implements ICalculatorDuplex.DivideBy
result /= n
equation += " / " + n.ToString()
callback.Equals(result)
End Sub
Public Sub MultiplyBy(ByVal n As Double) Implements ICalculatorDuplex.MultiplyBy
result *= n
equation += " * " + n.ToString()
callback.Equals(result)
End Sub
Public Sub SubtractFrom(ByVal n As Double) Implements ICalculatorDuplex.SubtractFrom
result -= n
equation += " - " + n.ToString()
callback.Equals(result)
End Sub
End Class
Door de ServiceContractAttribute en OperationContractAttribute kenmerken toe te passen, kan de automatische generatie van servicecontractdefinities in de WSDL (Web Services Description Language) worden gebruikt.
Gebruik het Hulpprogramma voor metagegevens van ServiceModel (Svcutil.exe) om het WSDL-document en (optionele) code en configuratie voor een client op te halen.
Eindpunten die dubbelzijdige services beschikbaar maken, moeten worden beveiligd. Wanneer een service een dubbelzijdig bericht ontvangt, wordt in dat binnenkomende bericht gekeken naar replyTo om te bepalen waar het antwoord moet worden verzonden. Als het kanaal niet is beveiligd, kan een niet-vertrouwde client een schadelijk bericht verzenden met de replyTo van een doelcomputer, wat leidt tot een denial of service van de doelcomputer. Bij normale berichten met een aanvraagantwoord is dit geen probleem, omdat de ReplyTo wordt genegeerd en het antwoord wordt verzonden op het kanaal waarop het oorspronkelijke bericht binnenkwam.