How to: Access Services with a Duplex Contract

One feature of Windows Communication Foundation (WCF) is the ability to create a service that uses a duplex messaging pattern. This pattern allows a service to communicate with the client through a callback. This topic shows the steps to create a WCF client in a client class that implements the callback interface.

A dual binding exposes the IP address of the client to the service. The client should use security to ensure that it connects only to services it trusts.

For a tutorial on creating a basic WCF service and client, see Getting Started Tutorial.

To access a duplex service

  1. Create a service that contains two interfaces. The first interface is for the service, the second is for the callback. For more information about creating a duplex service, see How to: Create a Duplex Contract.

  2. Run the service.

  3. Use the ServiceModel Metadata Utility Tool (Svcutil.exe) to generate contracts (interfaces) for the client. For information about how to do this, see How to: Create a Client.

  4. Implement the callback interface in the client class, as shown in the following example.

    public class CallbackHandler : ICalculatorDuplexCallback  
    {  
        public void Result(double result)  
        {  
            Console.WriteLine("Result ({0})", result);  
        }  
        public void Equation(string equation)  
        {  
            Console.WriteLine("Equation({0})", equation);  
        }  
    }  
    
    Public Class CallbackHandler   
    Implements ICalculatorDuplexCallback  
       Public Sub Result (ByVal result As Double)  
          Console.WriteLine("Result ({0})", result)  
       End Sub  
        Public Sub Equation(ByVal equation As String)  
            Console.Writeline("Equation({0})", equation)  
        End Sub  
    End Class  
    
  5. Create an instance of the InstanceContext class. The constructor requires an instance of the client class.

    InstanceContext site = new InstanceContext(new CallbackHandler());  
    
    Dim site As InstanceContext = New InstanceContext(new CallbackHandler())  
    
  6. Create an instance of the WCF client using the constructor that requires an InstanceContext object. The second parameter of the constructor is the name of an endpoint found in the configuration file.

    CalculatorDuplexClient wcfClient =   
    new CalculatorDuplexClient(site, "default")  
    
    Dim wcfClient As New CalculatorDuplexClient(site, "default")  
    
  7. Call the methods of the WCF client as required.

Example

The following code example demonstrates how to create a client class that accesses a duplex contract.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

// Define class that implements the callback interface of duplex 
// contract.
public class CallbackHandler : ICalculatorDuplexCallback
{
  public void Result(double result)
  {
    Console.WriteLine("Result({0})", result);
  }
  public void Equation(string equation)
  {
    Console.WriteLine("Equation({0})", equation);
  }
}


public class Client
{
  public static void Main()
  {
    // Picks up configuration from the config file.
    
    CalculatorDuplexClient wcfClient
      = new CalculatorDuplexClient(new InstanceContext(new CallbackHandler()));
    try
    {
      // Call the AddTo service operation.
      double value = 100.00D;
      wcfClient.AddTo(value);

      // Call the SubtractFrom service operation.
      value = 50.00D;
      wcfClient.SubtractFrom(value);

      // Call the MultiplyBy service operation.
      value = 17.65D;
      wcfClient.MultiplyBy(value);

      // Call the DivideBy service operation.
      value = 2.00D;
      wcfClient.DivideBy(value);

      // Complete equation.
      wcfClient.Clear();

      // Wait for callback messages to complete before
      // closing.
      System.Threading.Thread.Sleep(5000);

      // Close the WCF client.
      wcfClient.Close();
      Console.WriteLine("Done!");
    }
    catch (TimeoutException timeProblem)
    {
      Console.WriteLine("The service operation timed out. " + timeProblem.Message);
      wcfClient.Abort();
      Console.Read();
    }
    catch (CommunicationException commProblem)
    {
      Console.WriteLine("There was a communication problem. " + commProblem.Message);
      wcfClient.Abort();
      Console.Read();
    }
  }
}
Imports System
Imports System.ServiceModel

Namespace Microsoft.ServiceModel.Samples

    ' The service contract is defined in generatedClient.vb, generated from the service by the svcutil tool.

    ' Define class which implements callback interface of duplex contract
    Public Class CallbackHandler
        Implements ICalculatorDuplexCallback

        Public Sub Result(ByVal result As Double) Implements ICalculatorDuplexCallback.Result
            Console.WriteLine("Result({0})", result)
        End Sub

        Public Sub Equation(ByVal eqn As String) Implements ICalculatorDuplexCallback.Equation
            Console.WriteLine("Equation({0})", eqn)
        End Sub
    End Class

    Class Client
        Public Shared Sub Main()

            ' Construct InstanceContext to handle messages on callback interface
            Dim instanceContext As New InstanceContext(New CallbackHandler())

            ' Create a client
            Dim wcfClient As New CalculatorDuplexClient(instanceContext)
            Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.")
            Console.WriteLine()

            Try
                ' Call the AddTo service operation.
                Dim value As Double = 100
                wcfClient.AddTo(value)

                ' Call the SubtractFrom service operation.
                value = 50
                wcfClient.SubtractFrom(value)

                ' Call the MultiplyBy service operation.
                value = 17.65
                wcfClient.MultiplyBy(value)

                ' Call the DivideBy service operation.
                value = 2
                wcfClient.DivideBy(value)

                ' Complete equation
                wcfClient.Clear()

                Console.ReadLine()

                'Closing the client gracefully closes the connection and cleans up resources
                wcfClient.Close()

            Catch timeout As TimeoutException
                Console.WriteLine(timeout.Message)
                wcfClient.Abort()
            Catch commException As CommunicationException
                Console.WriteLine(commException.Message)
                wcfClient.Abort()
            End Try
        End Sub

    End Class

End Namespace

.NET Framework Security

See Also

Getting Started Tutorial
How to: Create a Duplex Contract
ServiceModel Metadata Utility Tool (Svcutil.exe)
How to: Create a Client
How to: Use the ChannelFactory