Vorgehensweise: Erstellen eines DuplexvertragsHow to: Create a Duplex Contract

Dieses Thema zeigt die grundlegenden Schritte zum Erstellen von Methoden, die einen Duplexvertrag (bidirektionalen Vertrag) verwenden.This topic shows the basic steps to create methods that use a duplex (two-way) contract. Ein Duplexvertrag ermöglicht die unabhängige Kommunikation zwischen Clients und Servern, sodass beide Aufrufe des jeweils Anderen initiieren können.A duplex contract allows clients and servers to communicate with each other independently so that either can initiate calls to the other. Der Duplexvertrag ist eines der drei Nachrichtenmuster, die für Windows Communication Foundation (WCF)Windows Communication Foundation (WCF)-Dienste verfügbar sind.The duplex contract is one of three message patterns available to Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) services. Die anderen beiden Nachrichtenmuster zeichnen sich durch unidirektionale Anforderungen bzw. Antworten aus.The other two message patterns are one-way and request-reply. Ein Duplexvertrag besteht aus zwei unidirektionalen Verträgen zwischen Client und Server und erfordert nicht, dass die Methodenaufrufe korrelieren.A duplex contract consists of two one-way contracts between the client and the server and does not require that the method calls be correlated. Sie verwenden diese Art von Vertrag, wenn der Dienst vom Client weitere Informationen anfordern muss oder auf dem Client ausdrücklich Ereignisse auslösen muss.Use this kind of contract when your service must query the client for more information or explicitly raise events on the client. Weitere Informationen finden Sie unterFor more information aboutErstellen eine Clientanwendung für einen Duplexvertrag finden Sie unter Vorgehensweise: Access Services mit einem Duplexvertrag. creating a client application for a duplex contract, see How to: Access Services with a Duplex Contract. Ein funktionierendes Beispiel finden Sie unter der Duplex Beispiel.For a working sample, see the Duplex sample.

So erstellen Sie einen DuplexvertragTo create a duplex contract

  1. Erstellen Sie die Schnittstelle, die die Serverseite des Duplexvertrags bildet.Create the interface that makes up the server side of the duplex contract.

  2. Wenden Sie die ServiceContractAttribute-Klasse auf die Schnittstelle an.Apply the ServiceContractAttribute class to the 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
    
    
  3. Deklarieren Sie die Methodensignaturen in der Schnittstelle.Declare the method signatures in the interface.

  4. Wenden Sie die OperationContractAttribute-Klasse auf jede Methodensignatur an, die Teil des öffentlichen Vertrags werden muss.Apply the OperationContractAttribute class to each method signature that must be part of the public contract.

  5. Erstellen Sie die Rückrufschnittstelle, mit der die Vorgänge definiert werden, die vom Dienst auf dem Clientendpunkt aufgerufen werden können.Create the callback interface that defines the set of operations that the service can invoke on the client.

    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 
    
    
  6. Deklarieren Sie die Methodesignaturen in der Rückrufschnittstelle.Declare the method signatures in the callback interface.

  7. Wenden Sie die OperationContractAttribute-Klasse auf jede Methodensignatur an, die Teil des öffentlichen Vertrags werden muss.Apply the OperationContractAttribute class to each method signature that must be part of the public contract.

  8. Verknüpfen Sie die beiden Schnittstellen zu einem Duplexvertrag, indem Sie die CallbackContract-Eigenschaft der primären Schnittstelle auf den Typ der Rückrufschnittstelle festlegen.Link the two interfaces into a duplex contract by setting the CallbackContract property in the primary interface to the type of the callback interface.

So rufen Sie Methoden auf dem Client aufTo call methods on the client

  1. Deklarieren Sie in der Dienstimplementierung des primären Vertrags eine Variable für die Rückrufschnittstelle.In the service's implementation of the primary contract, declare a variable for the callback interface.

  2. Legen Sie die Variable auf den von der GetCallbackChannel-Methode der OperationContext-Klasse zurückgegebenen Objektverweis fest.Set the variable to the object reference returned by the GetCallbackChannel method of the OperationContext class.

    ICalculatorDuplexCallback callback = null;
    
    Dim callback As ICalculatorDuplexCallback
    
    callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
    
    callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
    
  3. Rufen Sie die in der Rückrufschnittstelle definierten Methoden auf.Call the methods defined by the callback interface.

BeispielExample

Der folgende Beispielcode veranschaulicht die Duplexkommunikation.The following code example demonstrates duplex communication. Der Vertrag des Diensts enthält Dienstvorgänge zum vorwärts- und rückwärtsgerichteten Navigieren.The service’s contract contains service operations for moving forward and backward. Der Vertrag des Clients enthält einen Dienstvorgang zur Ausgabe seiner Position.The client’s contract contains a service operation for reporting its 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 opertion 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 opertion 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
  • Durch Anwenden des ServiceContractAttribute-Attributs und des OperationContractAttribute-Attributs wird die automatische Generierung von Dienstvertragsdefinitionen in WSDL (Web Services Description Language) ermöglicht.Applying the ServiceContractAttribute and OperationContractAttribute attributes allows the automatic generation of service contract definitions in the Web Services Description Language (WSDL).

  • Verwenden der ServiceModel Metadata Utility Tool (Svcutil.exe) zum Abrufen des WSDL-Dokument und (optional) Code und Konfiguration für einen Client.Use the ServiceModel Metadata Utility Tool (Svcutil.exe) to retrieve the WSDL document and (optional) code and configuration for a client.

  • Endpunkte, die Duplexdienste verfügbar machen, müssen geschützt werden.Endpoints exposing duplex services must be secured. 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.When a service receives a duplex message, it looks at the ReplyTo in that incoming message to determine where to send the reply. Wenn der zum Empfangen der Nachricht verwendete Kanal nicht geschützt ist, kann ein nicht vertrauenswürdiger Client eine bösartige Meldung mit dem ReplyTo-Element eines Zielcomputers senden, was auf diesem Zielcomputer zu einem Denial Of Service (DOS) führt.If the channel is not secured, then an untrusted client could send a malicious message with a target machine's ReplyTo, leading to a denial of service of the target machine. Bei gewöhnlichen Anforderung-Antwort-Nachrichten stellt dies kein Problem dar, weil das ReplyTo-Element ignoriert und die Antwort auf dem Kanal gesendet wird, auf dem die ursprüngliche Nachricht empfangen wurde.With regular request-reply messages, this is not an issue, because the ReplyTo is ignored and the response is sent on the channel the original message came in on.

Siehe auchSee Also

ServiceContractAttribute
OperationContractAttribute
Vorgehensweise: Zugreifen auf Dienste mit einem DuplexvertragHow to: Access Services with a Duplex Contract
DuplexDuplex
Entwerfen und Implementieren von DienstenDesigning and Implementing Services
Vorgehensweise: Definieren eines DienstvertragsHow to: Define a Service Contract
SitzungSession