Eliminate Server Polling with WCF Callbacks

Eliminate Server Polling with WCF Callbacks

he traditional ASMX web service request/response communication model is limiting, because it is passive?in other words, web services return results only when called by client code. For example, imagine a scenario in which a particular cinema operator deploys a web service so users can purchase tickets online. The cinema’s branches have systems that connect to the web service to obtain the current seat allocation and that sell tickets to cinema-goers. Using this model, the branch systems have to poll the web service regularly to get updated seat information. The model also makes it very likely that more than one branch system will attempt to book the same seat(s) at the same time.

A better approach would be for the web service to notify all the branches whenever seat status changes and a seat has been reserved. That way, all the branches would have the latest seat information, and remove the need to poll the web service, reducing the overall load. However, to accomplish this, you would need a communication model where the clients remain connected to the service, so they can be notified when an event occurs. Using WCF, you can implement this communication model using callbacks.

A callback allows a service to call back its clients. The roles of the service and the client are now reversed?the client becomes a service and the service becomes a client.

Build a WCF Ticketing Service
In this section you’ll see how to build a WCF ticketing service that allows clients to book tickets. When multiple clients are connected to the service, the system will broadcast seats booked by any client to all the connected clients. Figure 1 shows the system flow.

?
Figure 1. System Flow: In this system, seats booked by any client are broadcast to all other connected clients.
?
Figure 2. WCF Ticketing Web Service: Create a new WCF Service Library project and name it WcfTicketingService.

First, you need to create the WCF service that allows clients to book cinema tickets. Launch Visual Studio 2008 and create a new WCF Service Library project. Name it WcfTicketingService (see Figure 2).

In this example, the WCF service will be hosted by the WCF Service Host, a utility provided by Visual Studio 2008. When you create the project, you’ll see an IService1.cs file. Open that file and define the following service and data contracts (note that you can download the code for this project):

   using System;   using System.Collections.Generic;   using System.Linq;   using System.Runtime.Serialization;   using System.ServiceModel;   using System.Text;      namespace WcfTicketingService   {      [ServiceContract(         Name = "TicketingService,"         Namespace = "http://www.learn2develop.net/,"         CallbackContract = typeof(ITicketCallBack),         SessionMode = SessionMode.Required)]      public interface ITicketService      {         [OperationContract(IsOneWay = true)]         void SetSeatStatus(string strSeats);            [OperationContract(IsOneWay = true)]         void RegisterClient(Guid id);            [OperationContract(IsOneWay = true)]         void UnRegisterClient(Guid id);      }         public interface ITicketCallBack      {         [OperationContract(IsOneWay = true)]         void SeatStatus(string message);      }         //---each client connected to the service has a GUID---      [DataContract]      public class Client      {         [DataMember]         public Guid id { get; set; }      }   }

The ITicketService interface defines three operations:

  • SetSeatStatus: Allows clients to book seats. This operation accepts a string value containing the seats to be booked.
  • RegisterClient: Registers a client when it connects to the service. This operation accepts a GUID that uniquely identifies each client.
  • UnRegisterClient: Unregisters a client when it disconnects from the service. This operation accepts the client GUID.

Note that The ITicketService interface is decorated with the [ServiceContract] attribute. The CallbackContract property specifies the interface that defines the callback operation. In the preceding code, the SessionMode property is set to Required, indicating that state must be maintained between the service and client.

The other interface defined in the preceding code, the ITicketCallBack interface, contains only one operation?SeatStatus, which allows the service to initiate a callback to the client. The callback updates the client, letting it know which seats have been booked by other clients.

Finally, the Client class defines the data contract. Its single member holds the GUID of a client connecting to the service.

One-Way vs. Two-Way Operations
All the operations defined in the two interfaces are one-way operations (marked IsOneWay = true). To understand why, assume that all the operations use the default request/response model. When a client calls the SetSeatStatus() method to book seats, it will wait for a response from the service. However, the service will now invoke the SeatStatus callback on the client (the service informs all clients about the seats booked) and wait for a reply from the client. However, that would cause a deadlock, because the client would be waiting for a response from the service while the service would be waiting for a response from the client after invoking the callback. By defining the operations as one-way, the service can invoke the callback on the client without waiting for a reply from the client, thus eliminating the possibility of a deadlock.

Define the Classes
In the Service1.cs file, define the SeatStatus class:

   using System;   ...   using System.Text;   using System.Timers;      namespace WcfTicketingService   {      //...   }      public class SeatStatus   {      //---a string representing the seats booked by a client---      public string Seats { get; set; }   }

The SeatStatus class contains a property called Seats that stores the seats booked by a client.

Also in the Service1.cs file, define the Ticketing class, which implements the ITicketingService service contract (see Listing 1).

The Ticketing class contains the implementations for the three methods defined in the ITicketService interface:

  • RegisterClient(): Clients call this method when connecting to the service for the first time. The service stores the list of connected clients in a generic Dictionary object, using the GUID for the key, and it’s the client’s callback handler as the value.
  • UnRegisterClient(): Clients call this method when disconnecting from the service, which removes the calling client’s entry from the Dictionary object.
  • SetSeatStatus(): Clients call this method to book seats. The seats to be booked are stored in a SeatStatus object. When seats are booked, the Ticketing class creates an Action delegate that invokes the callback of each client, passing the newly-booked seats.

Near the top of the code in Listing 1, the [ServiceBehavior] attribute specifies the InstanceContextMode property as Single and the ConcurrencyMode property as Multiple. When a WCF Service receives a message, the message gets dispatched to an object’s instance methods. The options are:

  • A single instance of the receiver may be created for all clients
  • A single instance of the receiver may be created for each client

The InstanceContextMode property specifies the number of service instances available for handling calls contained in incoming messages. It can be one of the following:

  • Single: Every received message gets dispatched to the same object (a singleton).
  • Percall (default): Every received message is dispatched to a newly created object.
  • PerSession: Messages received within a session (usually a single sender) are dispatched to the same object.
  • Shareable: Messages received within a session (can be one or more senders) are dispatched to the same object.

You can also set how threads are used to manage all received messages, using either one thread at a time to access the receiver object(s), or using multiple threads to access the receiver object(s) concurrently.

The ConcurrencyMode property of the [ServiceBehavior] attribute controls how you handle all incoming messages. The property can assume of the following values:

  • Single (default): Only one thread may access the receiver object at a time
  • Multiple: Multiple threads may access the receiver object concurrently
  • Reentrant: Only one thread may access the receiver object at a time, but callbacks may re-enter that object on another thread

When you use the Multiple mode on the service, you need to take special care to make sure that threads are synchronized properly and that critical regions are locked during thread access.

To keep the demonstration simple, the sample project was developed using the following assumptions:

  • In real life, the application should save seats booked by a client in database or array; however for this example, they are simply broadcast to all connected clients.
  • When new clients connect to the server, the current seat allocation status (for instance, which seats are booked, which are not, etc.) should be sent to the client.

Now, double-click on the App.config file in Solution Explorer. Change the attribute values to match the following:

                                                                                             ...

Right-click on the App.config file and select Edit WCF Configuration. Expand the EndPoints node (see Figure 3) and select the first [Empty Name] node.

?
Figure 3. Endpoint Properties: Visual Studio provides UI for setting the endpoint properties stored in App.config.

?
Figure 4. WCF Test Client: Although the WCF Test Client shows errors, that’s normal for this application.

Set the endpoint properties as shown in Table 1.

Table 1. Endpoint Properties: Set the endpoint properties as shown in the table and illustrated in Figure 3.
Property Value
Address net.tcp://localhost:5000/TicketingService
Binding netTcpBinding

You will use TCP as the transport protocol.

Save the App.config file and close the configuration window. Press F5 to run and debug the service. In the WCF Test Client, you will see something like Figure 4. The error message is normal.

Building the Client
With the WCF service completed, you can now build the client that consumes the service. Using the same solution, add a new Windows Forms Application project, named Client.

Add a service reference to the WCF ticketing service (in the Add Service Reference dialog, click the Discover button and you should be able to discover the Ticketing WCF service (see Figure 5). Select it, and then click OK.

?
Figure 5. Add Service Reference: Using the Add Service Reference dialog, add a reference to the WCF ticketing service.
?
Figure 6. Sample Controls: Populate Form1 with the controls shown in this figure.

Next, populate Form1 with the controls shown in Figure 6. Set the form’s Size property to 477, 387.

In the code-behind for Form1, import the namespace shown below, and then declare the following constants and objects:

   using System.ServiceModel;   namespace Client   {      public partial class Form1 : Form      {         int ROWS = 10;         int COLUMNS = 10;         const int SEAT_WIDTH = 45;         const int SEAT_HEIGHT = 25;         const int START_X = 10;         const int START_Y = 40;            static Button[,] seatsArray;            private ServiceReference1.TicketingServiceClient _client;         private Guid _guid = Guid.NewGuid();

Define the SeatsOccupied() static function within the Form1 class as follows:

      public partial class Form1 : Form      {         ...         ...         ...         //---set all occupied seats in red---         public static void SeatsOccupied(string strSeatsOccupied)         {            string[] seats = strSeatsOccupied.Split(',');            for (int i = 0; i < seats.Length - 1; i++)            {               string[] xy = seats[i].Split('-');               Button btn = seatsArray[int.Parse(xy[0]) - 1,                   int.Parse(xy[1]) - 1];               btn.BackColor = Color.Red;            }         }      }

The SeatsOccupied function in the preceding code accepts a string containing the seats that are occupied. You'll see more about that in a minute. The seats themselves will be represented by button controls. Whenever a user books a seat (using the Button control), the application changes that seat's background color to red (meaning it's reserved).

Define the SeatStatusCallback class and implement the SeatStatus() method as defined in the TicketingServiceCallback interface (defined in the service):

   namespace Client   {      public partial class Form1 : Form      {         //...      }         public class SeatStatusCallback :          ServiceReference1.TicketingServiceCallback      {         public void SeatStatus(string message)         {            Form1.SeatsOccupied(message);         }      }   }

The client invokes the SeatStatus() method when the web service calls the client's callback. In this case, you call the static SeatsOccupied() function to update the seats status.

Code the Form1_Load event handler as follows:

   private void Form1_Load(object sender, EventArgs e)   {      InstanceContext context =         new InstanceContext(new SeatStatusCallback());      _client = new          ServiceReference1.TicketingServiceClient(context);      _client.RegisterClient(_guid);         //---display the seats---      seatsArray = new Button[COLUMNS, ROWS];      for (int r = 0; r < ROWS; r++)      {         for (int c = 0; c < ROWS; c++)         {            Button btn = new Button();            btn.Location = new Point(               START_X + (SEAT_WIDTH * c),               START_Y + (SEAT_HEIGHT * r));               btn.Size = new Size(SEAT_WIDTH, SEAT_HEIGHT);            btn.Text = (c + 1).ToString() + "-" +               (r + 1).ToString();            btn.BackColor = Color.White;            seatsArray[c, r] = btn;            btn.Click += new EventHandler(btn_Click);            this.Controls.Add(btn);         }      }   }

The preceding code basically creates an instance of the InstanceContext class by passing it an instance of the SeatStatusCallback class. It then creates an instance of the WCF client using the constructor (which requires an InstanceContext object). In addition, it dynamically populates the form with a 10x10 array of Button controls that represent the seats, and wires each Button control's Click event to the btn_Click event handler, shown below:

   void btn_Click(object sender, EventArgs e)   {      if (((Button)sender).BackColor == Color.White)      {         ((Button)sender).BackColor = Color.Yellow;      }      else if (((Button)sender).BackColor == Color.Yellow)      {         ((Button)sender).BackColor = Color.White;      }   }

This event handler toggles the color of the seats as users click on the Button controls. White indicates that the seat is available; yellow indicates that the seat has been selected for booking.

Code the Book Seats button as follows:

   private void btnBookSeats_Click(object sender, EventArgs e)   {      string seatsToBook = string.Empty;      for (int r = 0; r < ROWS; r++)      {         for (int c = 0; c < ROWS; c++)         {            if (seatsArray[c, r].BackColor == Color.Yellow)            {               seatsToBook += seatsArray[c, r].Text + ,"";            }         }      }      //---send to WCF service---      _client.SetSeatStatus(seatsToBook);   }

To specify the seats that are selected for booking, create the string containing the seats to be booked in the following format:

   -,-,…

Finally, code the Form1_FormClosing event so it calls the web service to unregister the client, as follows:

   private void Form1_FormClosing(object sender, FormClosingEventArgs e)   {      _client.UnRegisterClient(_guid);   }

Testing the Application
To test the application, press F5 to debug and launch the service. When it's running, you can debug the client. Right-click on the Client project in Solution Explorer, and select Debug ? Start new instance. (See Figure 7).

?
Figure 7. Launching the Client: To debug an instance of the client, right-click on the client project in Solution Explorer, and select Debug ( Start new instance.
?
Figure 8. Real-Time Updates: When one client books seats, all the clients get updated in near real-time.

Run a few instances of the client and you can then start to book cinema tickets. Notice that as one client books the seats, the service updates the other clients automatically (see Figure 8).

That completes the example. You've seen how you to use WCF callbacks to implement a cinema ticketing system, and you have an example you can extend to meet your own needs. Callbacks are advantageous because they allow asynchronous communications between a client and a service, and eliminate the need to constantly poll the service.

devx-admin

devx-admin

Share the Post:
5G Innovations

GPU-Accelerated 5G in Japan

NTT DOCOMO, a global telecommunications giant, is set to break new ground in the industry as it prepares to launch a GPU-accelerated 5G network in

AI Ethics

AI Journalism: Balancing Integrity and Innovation

An op-ed, produced using Microsoft’s Bing Chat AI software, recently appeared in the St. Louis Post-Dispatch, discussing the potential concerns surrounding the employment of artificial

Savings Extravaganza

Big Deal Days Extravaganza

The highly awaited Big Deal Days event for October 2023 is nearly here, scheduled for the 10th and 11th. Similar to the previous year, this

5G Innovations

GPU-Accelerated 5G in Japan

NTT DOCOMO, a global telecommunications giant, is set to break new ground in the industry as it prepares to launch a GPU-accelerated 5G network in Japan. This innovative approach will

AI Ethics

AI Journalism: Balancing Integrity and Innovation

An op-ed, produced using Microsoft’s Bing Chat AI software, recently appeared in the St. Louis Post-Dispatch, discussing the potential concerns surrounding the employment of artificial intelligence (AI) in journalism. These

Savings Extravaganza

Big Deal Days Extravaganza

The highly awaited Big Deal Days event for October 2023 is nearly here, scheduled for the 10th and 11th. Similar to the previous year, this autumn sale has already created

Cisco Splunk Deal

Cisco Splunk Deal Sparks Tech Acquisition Frenzy

Cisco’s recent massive purchase of Splunk, an AI-powered cybersecurity firm, for $28 billion signals a potential boost in tech deals after a year of subdued mergers and acquisitions in the

Iran Drone Expansion

Iran’s Jet-Propelled Drone Reshapes Power Balance

Iran has recently unveiled a jet-propelled variant of its Shahed series drone, marking a significant advancement in the nation’s drone technology. The new drone is poised to reshape the regional

Solar Geoengineering

Did the Overshoot Commission Shoot Down Geoengineering?

The Overshoot Commission has recently released a comprehensive report that discusses the controversial topic of Solar Geoengineering, also known as Solar Radiation Modification (SRM). The Commission’s primary objective is to

Remote Learning

Revolutionizing Remote Learning for Success

School districts are preparing to reveal a substantial technological upgrade designed to significantly improve remote learning experiences for both educators and students amid the ongoing pandemic. This major investment, which

Revolutionary SABERS Transforming

SABERS Batteries Transforming Industries

Scientists John Connell and Yi Lin from NASA’s Solid-state Architecture Batteries for Enhanced Rechargeability and Safety (SABERS) project are working on experimental solid-state battery packs that could dramatically change the

Build a Website

How Much Does It Cost to Build a Website?

Are you wondering how much it costs to build a website? The approximated cost is based on several factors, including which add-ons and platforms you choose. For example, a self-hosted

Battery Investments

Battery Startups Attract Billion-Dollar Investments

In recent times, battery startups have experienced a significant boost in investments, with three businesses obtaining over $1 billion in funding within the last month. French company Verkor amassed $2.1

Copilot Revolution

Microsoft Copilot: A Suit of AI Features

Microsoft’s latest offering, Microsoft Copilot, aims to revolutionize the way we interact with technology. By integrating various AI capabilities, this all-in-one tool provides users with an improved experience that not

AI Girlfriend Craze

AI Girlfriend Craze Threatens Relationships

The surge in virtual AI girlfriends’ popularity is playing a role in the escalating issue of loneliness among young males, and this could have serious repercussions for America’s future. A

AIOps Innovations

Senser is Changing AIOps

Senser, an AIOps platform based in Tel Aviv, has introduced its groundbreaking AI-powered observability solution to support developers and operations teams in promptly pinpointing the root causes of service disruptions

Bebop Charging Stations

Check Out The New Bebob Battery Charging Stations

Bebob has introduced new 4- and 8-channel battery charging stations primarily aimed at rental companies, providing a convenient solution for clients with a large quantity of batteries. These wall-mountable and

Malyasian Networks

Malaysia’s Dual 5G Network Growth

On Wednesday, Malaysia’s Prime Minister Anwar Ibrahim announced the country’s plan to implement a dual 5G network strategy. This move is designed to achieve a more equitable incorporation of both

Advanced Drones Race

Pentagon’s Bold Race for Advanced Drones

The Pentagon has recently unveiled its ambitious strategy to acquire thousands of sophisticated drones within the next two years. This decision comes in response to Russia’s rapid utilization of airborne

Important Updates

You Need to See the New Microsoft Updates

Microsoft has recently announced a series of new features and updates across their applications, including Outlook, Microsoft Teams, and SharePoint. These new developments are centered around improving user experience, streamlining

Price Wars

Inside Hyundai and Kia’s Price Wars

South Korean automakers Hyundai and Kia are cutting the prices on a number of their electric vehicles (EVs) in response to growing price competition within the South Korean market. Many

Solar Frenzy Surprises

Solar Subsidy in Germany Causes Frenzy

In a shocking turn of events, the German national KfW bank was forced to discontinue its home solar power subsidy program for charging electric vehicles (EVs) after just one day,

Electric Spare

Electric Cars Ditch Spare Tires for Efficiency

Ira Newlander from West Los Angeles is thinking about trading in his old Ford Explorer for a contemporary hybrid or electric vehicle. However, he has observed that the majority of

Solar Geoengineering Impacts

Unraveling Solar Geoengineering’s Hidden Impacts

As we continue to face the repercussions of climate change, scientists and experts seek innovative ways to mitigate its impacts. Solar geoengineering (SG), a technique involving the distribution of aerosols

Razer Discount

Unbelievable Razer Blade 17 Discount

On September 24, 2023, it was reported that Razer, a popular brand in the premium gaming laptop industry, is offering an exceptional deal on their Razer Blade 17 model. Typically

Innovation Ignition

New Fintech Innovation Ignites Change

The fintech sector continues to attract substantial interest, as demonstrated by a dedicated fintech stage at a recent event featuring panel discussions and informal conversations with industry professionals. The gathering,

Import Easing

Easing Import Rules for Big Tech

India has chosen to ease its proposed restrictions on imports of laptops, tablets, and other IT hardware, allowing manufacturers like Apple Inc., HP Inc., and Dell Technologies Inc. more time