HOW TO:建立雙面合約How to: Create a Duplex Contract

本主題說明的基本步驟可用來建立使用雙工 (雙向) 合約的方法。This topic shows the basic steps to create methods that use a duplex (two-way) contract. 雙工合約可供用戶端與伺服器彼此各自進行通訊,方便任何一方初始化對另一方的呼叫。A duplex contract allows clients and servers to communicate with each other independently so that either can initiate calls to the other. 雙工合約是其中一個可用於 Windows Communication Foundation (WCF) 服務的三種訊息模式。The duplex contract is one of three message patterns available to Windows Communication Foundation (WCF) services. 其他兩種訊息模式分別是單向和要求-回覆。The other two message patterns are one-way and request-reply. 雙工合約是由用戶端和伺服器之間的兩個單向合約組成,而且不需要相互關聯方法呼叫。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. 當您的服務必須查詢用戶端以獲得更多資訊,或是明確地在用戶端上引發事件時,請使用這種合約。Use this kind of contract when your service must query the client for more information or explicitly raise events on the client. 如需建立雙工合約的用戶端應用程式的詳細資訊,請參閱How to:使用雙工合約存取服務For more information about creating a client application for a duplex contract, see How to: Access Services with a Duplex Contract. 如需實用範例,請參閱 < 雙工範例。For a working sample, see the Duplex sample.

若要建立雙工合約To create a duplex contract

  1. 建立可組成雙工合約伺服器端的介面。Create the interface that makes up the server side of the duplex contract.

  2. ServiceContractAttribute 類別套用到介面。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. 在介面中宣告方法簽章。Declare the method signatures in the interface.

  4. OperationContractAttribute 類別套用到每個必須是公用合約一部分的方法簽章上。Apply the OperationContractAttribute class to each method signature that must be part of the public contract.

  5. 建立可定義作業集合 (供服務在用戶端上加以叫用) 的回呼介面。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. 在回呼介面中宣告方法簽章。Declare the method signatures in the callback interface.

  7. OperationContractAttribute 類別套用到每個必須是公用合約一部分的方法簽章上。Apply the OperationContractAttribute class to each method signature that must be part of the public contract.

  8. 將主要介面中的 CallbackContract 屬性設為回呼介面的型別,以將兩個介面連接至雙工合約。Link the two interfaces into a duplex contract by setting the CallbackContract property in the primary interface to the type of the callback interface.

若要在用戶端上呼叫方法To call methods on the client

  1. 在服務的主要合約實作中,宣告回呼介面的變數。In the service's implementation of the primary contract, declare a variable for the callback interface.

  2. 將變數設為由 GetCallbackChannel 類別之 OperationContext 方法傳回的物件參考。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. 呼叫回呼介面定義的方法。Call the methods defined by the callback interface.

範例Example

下列程式碼範例會示範雙工通訊。The following code example demonstrates duplex communication. 服務合約包含可往前與往後的服務作業。The service’s contract contains service operations for moving forward and backward. 用戶端合約包含可報告自身位置的服務作業。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
  • 套用 ServiceContractAttributeOperationContractAttribute 屬性可自動產生 Web 服務描述語言 (WSDL) 格式的服務合約定義。Applying the ServiceContractAttribute and OperationContractAttribute attributes allows the automatic generation of service contract definitions in the Web Services Description Language (WSDL).

  • 使用ServiceModel Metadata Utility Tool (Svcutil.exe)擷取 WSDL 文件和 (選擇性) 的程式碼和用戶端組態。Use the ServiceModel Metadata Utility Tool (Svcutil.exe) to retrieve the WSDL document and (optional) code and configuration for a client.

  • 您必須保護公開雙工服務的端點安全。Endpoints exposing duplex services must be secured. 當服務收到雙工訊息時,會查看該傳入訊息中的 ReplyTo 項目,以判斷傳送回覆的位置。When a service receives a duplex message, it looks at the ReplyTo in that incoming message to determine where to send the reply. 如果通道不安全,那麼未受信任的用戶端可能會傳送惡意訊息,其中包含目標電腦的 ReplyTo,而導致該目標電腦發生阻絕服務。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. 如果是一般的要求-回覆訊息,這根本不是問題,因為電腦會忽略 ReplyTo 並且在原始傳入訊息所用的通道上傳送回應。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.

另請參閱See also