WCF: Reliable Messaging

In this article, I will explain what reliable messaging is and how it’s implemented in a WCF web service.

What Is Reliable Messaging?

 
WCF reliable messaging makes web services more reliable. It addresses two problems:
 
A call to a web service travels across a network. Networks are not perfectly reliable. They sometimes suffer congestion and dropped signals. Sometimes calls don't make it to the web service, or the responses don't make it back. If I'm trying to run my business using web services, reliability is a serious issue.
 
If I make several calls to a web service across a large network, there's a possibility that the calls won't arrive at the service in the same order that I made them. If it's important that my calls be processed in order, this is a problem.
 
WCF reliable messaging makes sending reliable, ordered messages over unreliable networks simple.
 
When your web service is set up with WCF message reliability, it implements the WS-ReliableMessaging protocol. Like WS-Addressing and WS-Security, this is a commonly implemented cross-platform standard. When both the client and the service implement WS-ReliableMessaging, they can establish a back and forth communication that helps ensure that calls and responses are received. Reliable messaging works over HTTP, TCP, and Named Pipe bindings.
 
Reliable messaging works a little like TCP (the transport part of TCP/IP). Communication between the client and the service goes something like this:
 
Client: I want to make a call.
Service: OK, here's an ID.
 
Client: Here is message #1.
Service: I received message #1.
 
Client: Here is message #2.
[no response from the service]
 
Client: Here is message #2.
Service: I received message #2.
 
Client: I am done sending messages.
Service: OK, thank you.
 
In this example, the client didn't get a response the first time it sent message #2. Maybe the service didn't get the call. Maybe it got the call, but the response didn't make it back. Whatever the cause, the client tries again. If the service actually receives message #2 twice, it will ignore the second call.
 
Notice that each message sent to the service was given a sequence number. If the service receives the messages out of order, it stores them as needed in order to process all the messages in order.
 
For this kind of back and forth communication to work, both the web service and the client have to implement WS-ReliableMessaging.
 

How To Set Up Reliable Messaging

 
Setting up reliable messaging is simple - a few lines in your WCF web service .config file.
  1. <system.serviceModel>  
  2.      <services>  
  3.           <service name="MyService">  
  4.                 <endpoint   
  5.                     binding="wsHttpBinding"   
  6.                     bindingConfiguration="MyBinding"   
  7.                     ...     
  8.                </endpoint>  
  9.           </service>  
  10.      </services>  
  11.      <bindings>  
  12.           <wsHttpBinding>  
  13.                <binding name="MyBinding" ... >  
  14.                     <reliableSession   
  15.                          enabled="true"   
  16.                          ordered="true"   
  17.                          inactivityTimeout="00:03:00" />  
  18.                </binding>  
  19.           </wsHttpBinding>  
  20.      </bindings>  
  21. </system.serviceModel>  
I've set three values for reliable messaging: 
 
enabled:
By default this is false. Setting it to true enables reliable messaging.
 
ordered:
Ordered message processing can only be enabled if reliableSession is enabled. If reliableSession is enabled, ordered message processing is also enabled by default, but it can be turned off by setting this value to false. If turned off, messages are processed in the order received.
 
inactivityTimeout:
This setting specifies how long a session can remain open with no messages received before it times out. The default value is ten minutes.
 
A WCF client uses the same settings to enable reliable messaging.
 

The RequireOrderedDelivery Attribute

 
Normally the service contract and the binding are independent. You write the contract and the code to implement it, and the resulting service can be run on any binding. In the case of ordered messaging, however, you can add an attribute to the contract so that it will only run in bindings where ordered delivery is enabled.
  1. [DeliveryRequirement(RequireOrderedDelivery=true)]  
  2. [ServiceContract]  
  3. interface IMyContract  
  4. {  
  5.      ...  
  6. }  
or you can put it on a class that implements the interface: 
  1. [DeliveryRequirement(RequireOrderedDelivery=true)]  
  2. class MyService : IMyContract  
  3. {  
  4.      ...  
  5. }  
In this case, you can have one class that implements IMyContract which requires ordered messages and a different class that implements the same interface, but which does not require it.