Procédure : créer un contrat duplex

Cette rubrique décrit les étapes de base pour créer des méthodes qui utilisent un contrat duplex (bidirectionnel). Un contrat duplex autorise les clients et les serveurs à communiquer entre eux indépendamment de sorte que l'un puisse initier des appels à l'autre. Le contrat duplex est l’un des trois modèles de message disponibles pour les services Windows Communication Foundation (WCF). Les deux autres modèles de message sont unidirectionnels et demande/réponse. Un contrat duplex se compose de deux contrats unidirectionnels entre le client et le serveur et ne requiert pas que les appels de méthode soient corrélés. Utilisez ce type de contrat lorsque votre service doit demander au client plus d'informations ou déclencher explicitement des événements sur le client. Pour plus d’informations sur la création d’une application cliente pour un contrat duplex, consultez Comment : accéder aux services ayant un contrat duplex. Pour obtenir un exemple fonctionnel, consultez l’exemple Duplex.

Pour créer un contrat duplex

  1. Créez l'interface constitutive du côté serveur du contrat duplex.

  2. Appliquez la classe ServiceContractAttribute à l'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. Déclarez les signatures de méthode dans l'interface.

  4. Appliquez la classe OperationContractAttribute à chaque signature de méthode qui doit faire partie du contrat public.

  5. Créez l'interface de rappel qui définit le jeu des opérations que le service peut appeler sur le 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. Déclarez les signatures de méthode dans l'interface de rappel.

  7. Appliquez la classe OperationContractAttribute à chaque signature de méthode qui doit faire partie du contrat public.

  8. Liez les deux interfaces dans un contrat duplex en affectant à la propriété CallbackContract dans l'interface primaire le type de l'interface de rappel.

Pour appeler des méthodes sur le client

  1. Dans l'implémentation de service du contrat principal, déclarez une variable pour l'interface de rappel.

  2. Affectez à la variable la référence d'objet retournée par la méthode GetCallbackChannel de la classe OperationContext.

    ICalculatorDuplexCallback callback = null;
    
    Dim callback As ICalculatorDuplexCallback
    
    callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
    
    callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
    
  3. Appelez les méthodes définies par l'interface de rappel.

Exemple

L'exemple de code suivant illustre la communication duplex. Le contrat du service contient des opérations de service pour avancer et reculer. Le contrat du client contient une opération de service pour indiquer sa 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
  • Appliquer les attributs ServiceContractAttribute et OperationContractAttribute permet la génération automatique de définitions de contrat de service dans WSDL (Web Services Description Language).

  • Utilisez l’Outil utilitaire Service Model Metadata (Svcutil.exe) pour récupérer le document WSDL et (facultatif) du code et de la configuration pour un client.

  • Les points de terminaison qui exposent des services duplex doivent être sécurisés. Lorsqu'un service reçoit un message duplex, il consulte l'élément ReplyTo dans ce message entrant afin de déterminer où envoyer la réponse. Si le canal n'est pas sécurisé, un client non fiable peut envoyer un message malveillant avec le ReplyTo d'un ordinateur cible, ce qui peut entraîner à un déni de service de l'ordinateur cible. Avec les messages de réponse/demande normaux, ce problème ne se pose pas, parce que le ReplyTo est ignoré et la réponse est envoyée sur le canal sur lequel le message d'origine est arrivé.

Voir aussi