Click here to Skip to main content
15,877,280 members
Articles / Programming Languages / C#

Push model(Callback, WSDualHttpBinding) overview

Rate me:
Please Sign up or sign in to vote.
4.31/5 (9 votes)
1 Nov 2014CPOL3 min read 32.5K   1.1K   12   9
WCF service example to explain how and when to implement callback model (WSDualHttpBinding)

Prerequisite 

Reader of this article should have basic understanding of WCF, End points, Visual studio and bindings.

Background 

In our day to day operations we come across scenarios where we have to reflect changes on client when there is some change done sever. One way is to implement polling model where client will keep on polling server to check changes but this approach is very inefficient better way is to implement a mechanism where server can push client to reflect update whenever corresponding change occurs on server. WCF provide WSDualHttpBinding or (Duplex) to achieve same very efficiently. Below I have described set by step example to explain implementation.

Introduction 

In the example described below a client application is sending a request to server for registration of name. On registration, server is sending a notification to client for successful registration. To make the notification more responsive I have used timer to send notification in intervals.

This example has three components

  1. Service library - Server with DuplexServiceLibrary (WCF service library) which have implementation of service & service contracts.
  2. Service host – A console application to host the service.
  3. Client – A console application to act as client (consumer of service)

Implementing server

In visual studio add new project, add WCF Service library. Here VS 2012 is used but VS 2008 can also be used 

Image 1

Below is the service contract IDuplexService containing the method for registration. To keep simple only one method is added in it. We need to add CallbackContract attribute to define callback service interface for 

C#
[ServiceContract(SessionMode = SessionMode.Required,
                CallbackContract = typeof(IDuplexServiceCallback))]
 public interface IDuplexService {

   [OperationContract(IsOneWay = true)]
   void Registration(string Name);

 }

Below is the callback Interface definition which consists of NotifyRegistration method which will result in sending notification to clients. OperationContract message exchange pattern is one way (IsOneWay = true) because in this case only one message is transmitted. The receiver does not send a reply message, nor does the sender expect one.

C#
[ServiceContract]
  public interface IDuplexServiceCallback {

    [OperationContract(IsOneWay = true)]
    void NotifyRegistration(string Name);        
  }

Implement the DuplexService for Registration. Here timer is used to invoke callback method at regular interval which can be update client respectively.

C#
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class DuplexService : IDuplexService
    {

        #region IDuplexService Members

        string result = "Your request has been regitered by Application ";
        public static Timer Timer;
        public static IDuplexServiceCallback Callback;

        public DuplexService()
        {            
        }

        public void Registration(string Name)
        {
            Callback = OperationContext.Current.GetCallbackChannel<IDuplexServiceCallback>();
            result = Name + " :: " + result;
            Timer = new Timer(1000);
            Timer.Elapsed += OnTimerElapsed;
            Timer.Enabled = true;
        }

        void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            string notification = result + " @ " + DateTime.Now.ToString();
            Callback.NotifyRegistration(notification);
        }

Now we need to define end point on server. For call back service (push model) we need wsDualHttpBinding. Below is the complete app.config code for service.

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service name="DuplexServiceLibrary.DuplexService">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8090/DuplexService/" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address="" binding="wsDualHttpBinding" contract="DuplexServiceLibrary.IDuplexService">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

</configuration>

Implementing service host

Now with service ready we now have to implement service host. We can use new command line application to create a host name DuplexServiceHost. Add reference of DuplexServiceLibrary and initialize the service host 

 Image 2

C#
static void Main(string[] args) {

     ServiceHost host = new ServiceHost(typeof(DuplexService));

     ConsoleColor oldColour = Console.ForegroundColor;
     Console.ForegroundColor = ConsoleColor.Yellow;

     Console.WriteLine("DuplexService is up and running with the following endpoints:");
     foreach (ServiceEndpoint se in host.Description.Endpoints)
       Console.WriteLine(se.Address.ToString());
     Console.ReadLine();

     host.Open();

     host.Close();
   }

Now add new App.config file to this console application and copy the app.config of the DuplexService.

Implementing Client.

Add new console application (name DuplexClient ) to the solution and rename class program to client (just to have different name from service host). Now add service reference to client with  namespace DuplexServiceReference

 Image 3

Adding service reference will add new app.config to the client with required endpoints.

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <wsDualHttpBinding>
        <binding name="WSDualHttpBinding_IDuplexService" clientBaseAddress="http://localhost:8091/" />
      </wsDualHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:8090/DuplexService/" binding="wsDualHttpBinding"
        bindingConfiguration="WSDualHttpBinding_IDuplexService" contract="DuplexServiceReference.IDuplexService"
        name="WSDualHttpBinding_IDuplexService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

Now implement Client. Define duplexClient for the service as below.

C#
private static DuplexServiceReference.DuplexServiceClient duplexClient;

Define new class to implement the NotifyRegistration method of the IDuplexServiceCallback contract as shown below

C#
public class DuplexServiceCallBackHandler : DuplexServiceReference.IDuplexServiceCallback{

        public void NotifyRegistration(string Name){
            ConsoleColor oldColour = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Notification : ({0})", Name);
        }

    }

Instantiate the context for the service in Main method.

C#
InstanceContext context = new InstanceContext(new DuplexServiceCallBackHandler());
            duplexClient = new DuplexServiceReference.DuplexServiceClient(context, "WSDualHttpBinding_IDuplexService");

Call the registration method of the service

C#
duplexClient.Registration(name);
Console.ReadLine();

Complete implementation of Client is given below.

C#
class Client{
     private static DuplexServiceReference.DuplexServiceClient duplexClient;
     static void Main(string[] args){

         InstanceContext context = new InstanceContext(new DuplexServiceCallBackHandler());
         duplexClient = new DuplexServiceReference.DuplexServiceClient(context, "WSDualHttpBinding_IDuplexService");
         try{

             Console.WriteLine("This is a client, press enter initiate request to server");
             Console.ReadLine();
             string name = "Sudhir";
             duplexClient.Registration(name);
             Console.ReadLine();
         }

         catch (TimeoutException timeProblem){
             Console.WriteLine("The service operation timed out. " + timeProblem.Message);
             duplexClient.Abort();
             Console.Read();
         }
         catch (CommunicationException commProblem){
             Console.WriteLine("There was a communication problem. " + commProblem.Message);
             duplexClient.Abort();
             Console.Read();
         }
     }
 }

 public class DuplexServiceCallBackHandler : DuplexServiceReference.IDuplexServiceCallback
 {
     public void NotifyRegistration(string Name){
         ConsoleColor oldColour = Console.ForegroundColor;
         Console.ForegroundColor = ConsoleColor.Yellow;
         Console.WriteLine("Notification : ({0})", Name);
     }
 }

Now with client and server ready go to solution properties and set multiple startup projects

Image 4

Now build solution and run. It will show two command prompts. One for service host which shows the service endpoint defined. Other one is client. As per logic written in client press enter to register on server with defined interval on server client will be updated with the notification. Please ensure to run Visual studio in Admin mode.

Image 5

Complete solution can be downloaded to see the implementation. 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionTried to debug DuplexClient only, got same result Pin
TranQuangDao29-Apr-20 0:26
professionalTranQuangDao29-Apr-20 0:26 
Questiongetting an error if deployed in production Pin
makoychan9-Dec-17 15:25
makoychan9-Dec-17 15:25 
QuestionIt works, but... Pin
Dewey2-Nov-14 10:28
Dewey2-Nov-14 10:28 
AnswerRe: It works, but... Pin
Sudhir Dutt Rawat2-Nov-14 17:17
Sudhir Dutt Rawat2-Nov-14 17:17 
QuestionNot sure it explains enough Pin
CHill602-Nov-14 4:26
mveCHill602-Nov-14 4:26 
AnswerRe: Not sure it explains enough Pin
Sudhir Dutt Rawat2-Nov-14 5:37
Sudhir Dutt Rawat2-Nov-14 5:37 
GeneralMy vote of 5 Pin
majid torfi2-Nov-14 2:56
professionalmajid torfi2-Nov-14 2:56 
BugImage links Pin
Viacheslav.K2-Nov-14 0:42
professionalViacheslav.K2-Nov-14 0:42 
GeneralRe: Image links Pin
Sudhir Dutt Rawat2-Nov-14 1:41
Sudhir Dutt Rawat2-Nov-14 1:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.