Instrukcje: Tworzenie kontraktu dwukierunkowego

W tym temacie przedstawiono podstawowe kroki tworzenia metod korzystających z kontraktu dwukierunkowego (dwukierunkowego). Kontrakt dwukierunkowy umożliwia klientom i serwerom komunikowanie się ze sobą niezależnie, dzięki czemu każdy z nich może inicjować wywołania do drugiego. Kontrakt dwukierunkowy jest jednym z trzech wzorców komunikatów dostępnych dla usług Windows Communication Foundation (WCF). Pozostałe dwa wzorce komunikatów są jednokierunkowe i żądanie-odpowiedź. Kontrakt dwukierunkowy składa się z dwóch jednokierunkowych kontraktów między klientem a serwerem i nie wymaga korelowania wywołań metod. Tego rodzaju kontraktu należy użyć, gdy usługa musi wysłać zapytanie do klienta, aby uzyskać więcej informacji lub jawnie zgłosić zdarzenia na kliencie. Aby uzyskać więcej informacji na temat tworzenia aplikacji klienckiej dla kontraktu dwustronnego, zobacz Instrukcje: Usługi programu Access z kontraktem dwukierunkowym. Aby zapoznać się z przykładem roboczym, zobacz przykład Dupleks .

Aby utworzyć kontrakt dwukierunkowy

  1. Utwórz interfejs tworzący stronę serwera kontraktu dwustronnego.

  2. Zastosuj klasę ServiceContractAttribute do interfejsu.

    [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. Zadeklaruj podpisy metody w interfejsie.

  4. Zastosuj klasę OperationContractAttribute do każdego podpisu metody, który musi być częścią umowy publicznej.

  5. Utwórz interfejs wywołania zwrotnego, który definiuje zestaw operacji, które usługa może wywołać na kliencie.

    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. Zadeklaruj podpisy metody w interfejsie wywołania zwrotnego.

  7. Zastosuj klasę OperationContractAttribute do każdego podpisu metody, który musi być częścią umowy publicznej.

  8. Połącz dwa interfejsy z kontraktem dwudupleksowym, ustawiając CallbackContract właściwość w interfejsie podstawowym na typ interfejsu wywołania zwrotnego.

Aby wywołać metody na kliencie

  1. W implementacji kontraktu podstawowego usługi zadeklaruj zmienną dla interfejsu wywołania zwrotnego.

  2. Ustaw zmienną na odwołanie do obiektu zwrócone GetCallbackChannel przez metodę OperationContext klasy.

    ICalculatorDuplexCallback callback = null;
    
    Dim callback As ICalculatorDuplexCallback
    
    callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
    
    callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
    
  3. Wywołaj metody zdefiniowane przez interfejs wywołania zwrotnego.

Przykład

W poniższym przykładzie kodu pokazano komunikację dwukierunkową. Kontrakt usługi zawiera operacje usługi na potrzeby przechodzenia do przodu i do tyłu. Kontrakt klienta zawiera operację usługi do raportowania swojej pozycji.

// 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
  • ServiceContractAttribute Zastosowanie atrybutów i OperationContractAttribute umożliwia automatyczne generowanie definicji kontraktów usług w języku WSDL (Web Services Description Language).

  • Użyj narzędzia ServiceModel Metadata Tool (Svcutil.exe), aby pobrać dokument WSDL i (opcjonalnie) kod i konfigurację klienta.

  • Punkty końcowe ujawniające usługi dwukierunkowe muszą być zabezpieczone. Gdy usługa odbiera komunikat dwukierunkowy, analizuje element ReplyTo w tej wiadomości przychodzącej, aby określić, gdzie wysłać odpowiedź. Jeśli kanał nie jest zabezpieczony, niezaufany klient może wysłać złośliwy komunikat z odpowiedzią do maszyny docelowej, co prowadzi do odmowy usługi maszyny docelowej. W przypadku zwykłych wiadomości z odpowiedzią na żądanie nie jest to problem, ponieważ funkcja ReplyTo jest ignorowana, a odpowiedź jest wysyłana w kanale, w ramach którego pojawiła się oryginalna wiadomość.

Zobacz też