Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Thema werden die grundlegenden Schritte erläutert, um Methoden zu erstellen, die einen Duplex-Vertrag verwenden. Mit einem Duplex-Vertrag können Clients und Server unabhängig voneinander kommunizieren, sodass beide Aufrufe an die andere initiieren können. Der Duplex-Vertrag ist eines von drei Nachrichtenmustern, die für Windows Communication Foundation (WCF)-Dienste verfügbar sind. Die anderen beiden Nachrichtenmuster sind Einweg und Anfrage-Antwort. Ein Duplex-Vertrag besteht aus zwei unidirektionalen Verträgen zwischen dem Client und dem Server und erfordert nicht, dass die Methodenaufrufe korreliert werden müssen. Verwenden Sie diese Art von Vertrag, wenn Ihr Dienst den Client nach weiteren Informationen abfragen oder explizit Ereignisse auf dem Client auslösen muss. Weitere Informationen zum Erstellen einer Clientanwendung für einen Duplex-Vertrag finden Sie unter How to: Access Services with a Duplex Contract. Ein Arbeitsbeispiel finden Sie im Duplexbeispiel .
So erstellen Sie einen Duplex-Vertrag
Erstellen Sie die Schnittstelle, aus der sich die Serverseite des Duplexvertrags ergibt.
Wenden Sie die ServiceContractAttribute Klasse auf die Schnittstelle an.
[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 InterfaceDeklarieren Sie die Methodensignaturen in der Schnittstelle.
Wenden Sie die OperationContractAttribute Klasse auf jede Methodensignatur an, die Teil des öffentlichen Vertrags sein muss.
Erstellen Sie die Rückrufschnittstelle, die den Satz von Vorgängen definiert, die der Dienst auf dem Client aufrufen kann.
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 interfaceDeklarieren Sie die Methodensignaturen in der Rückrufschnittstelle.
Wenden Sie die OperationContractAttribute Klasse auf jede Methodensignatur an, die Teil des öffentlichen Vertrags sein muss.
Verknüpfen Sie die beiden Schnittstellen mit einem Duplex-Vertrag, indem Sie die CallbackContract Eigenschaft in der primären Schnittstelle auf den Typ der Rückrufschnittstelle festlegen.
So rufen Sie Methoden auf dem Client auf
Deklarieren Sie in der Implementierung des primären Vertrags eine Variable für die Rückrufschnittstelle.
Legen Sie die Variable auf den Objektverweis fest, der von der GetCallbackChannel Methode der OperationContext Klasse zurückgegeben wird.
ICalculatorDuplexCallback callback = null;Dim callback As ICalculatorDuplexCallbackcallback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()Rufen Sie die von der Rückrufschnittstelle definierten Methoden auf.
Beispiel
Im folgenden Codebeispiel wird die Duplexkommunikation veranschaulicht. Der Vertrag des Services enthält Vorgänge für das Vorwärts- und Rückwärtsbewegen. Der Vertrag des Kunden enthält einen Dienstvorgang zum Melden seiner Position.
// 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
Das Anwenden des ServiceContractAttribute- und OperationContractAttribute-Attributs ermöglicht die automatische Generierung von Dienstvertragsdefinitionen in der Webdienstbeschreibungssprache (WSDL).
Verwenden Sie das ServiceModel Metadata Utility Tool (Svcutil.exe), um das WSDL-Dokument sowie (optional) den Code und die Konfiguration für einen Client abzurufen.
Endpunkte, die Duplexdienste zur Verfügung stellen, müssen gesichert sein. Wenn ein Dienst eine Duplexnachricht empfängt, überprüft er das ReplyTo-Element in dieser eingehenden Nachricht, um zu bestimmen, wohin die Antwort gesendet werden soll. Wenn der Kanal nicht gesichert ist, kann ein nicht vertrauenswürdiger Client eine schädliche Nachricht mit dem ReplyTo eines Zielcomputers senden, was zu einem Denial of Service des Zielcomputers führt. Bei regulären Anforderungsantwortnachrichten ist dies kein Problem, da "ReplyTo" ignoriert wird und die Antwort auf dem Kanal gesendet wird, an den die ursprüngliche Nachricht gesendet wurde.