In this article, we will see what message exchange in WCF is and what are the patterns available to exchange the message. We will also see how to do it.
What is Message Exchange Pattern?
It is nothing but something that describes how the client and service will exchange the messages between them. In WCF, there are three types of patterns available to exchange the message:
- Request and response
- One-way communication
- Duplex communication
Request and Response Pattern
The client will send the request to the WCF service and the service will return the response back to the client after completing the operation in service. The client will wait for the service response during this time. It will happen even if the method is void in the operation contract.
All WCF bindings will support the request –response pattern except MSMQ. During this communication the client will get an exception if it occurs in service.
This is the default message exchange pattern in WCF, if we do not specify anything in the WCF service.
Sample
- [ServiceContract]
- public interface IHelloService
- {
- [OperationContract]
- string SayHello(string name);
- }
OR
- [ServiceContract]
- public interface IHelloService
- {
- [OperationContract(IsOneWay=false)]
- string SayHello(string name);
- }
Note the above two codes. In one operation contract I mentioned the IsOneWay property as false and I did not mention it in another one. Both are equal in WCF. The default message exchange pattern is request-reply in WCF.
One-way communication
The client only sends the request to the service and it will not wait for the response back from the service. The client will not get any exceptions if it is occurring during the service processing it, because the client is not waiting for the result here.
Here, the client will not wait for the response from the service. The service operation’s return type may be anything. But we can’t get the result in the client.
Sample Code - [ServiceContract]
- public interface IUser
- {
- [OperationContract(IsOneWay = true)]
- void ChangeLoginState(bool state);
- }
- public class User: IUser
- {
- void IUser.ChangeLoginState(bool state)
- {
- Thread.Sleep(7000);
- }
- }
Client application code - ServiceRef.UserClient client = new ServiceRef.UserClient();
- client.ChangeLoginState(true);
- Console.ReadKey();
Here we will find the difference between request-reply and one way communication by setting the
IsOneWay property as false in the operation contract.
Duplex Communication
The client sends a request in one channel and the server will send a response in another channel. The service exception may or may not be thrown to the client depending on the implementation.
We will implement the duplex communication in two ways.
First Way
Step 1: Create service library and add the service and callback interface as below.
- [ServiceContract(CallbackContract = typeof (IStatusCallBack))]
- public interface IStatusServie
- {
- [OperationContract(IsOneWay = true)]
- void NotifyStatus();
- }
- public interface IStatusCallBack
- {
- [OperationContract(IsOneWay = true)]
- void Progress(int percent);
- }
The callback interface only has the operation contract without service contract attributes and both the operation contract marked with IsOneWay property. Here they are going to communicate independently.
Step 2: Add the one console project to host the service in self host and implement the following code in the class.
- Console.WriteLine("Try to start service.");
- ServiceHost host = new ServiceHost(typeof (DuplexService.StatusServie));
- host.Open();
- Console.WriteLine("The service started successfully.");
- Console.ReadKey();
Step 3: Add the following configuration in service host project.
- <system.serviceModel>
- <services>
- <service name="DuplexService.StatusServie" behaviorConfiguration="mexBehaviour">
- <endpoint address="StatusServie" binding="netTcpBinding" contract="DuplexService.IStatusServie"></endpoint>
- <host>
- <baseAddresses>
- <add baseAddress="http://localhost:8085" />
- <add baseAddress="net.tcp://localhost:8086" /> </baseAddresses>
- </host>
- </service>
- </services>
- <behaviors>
- <serviceBehaviors>
- <behavior name="mexBehaviour">
- <serviceMetadata httpGetEnabled="true" /> </behavior>
- </serviceBehaviors>
- </behaviors>
- </system.serviceModel>
Step 4: Build the application and run the server project in the administrator mode.
Step 5: Now the service will be running. Create one client project and capture the service using the URL
http://localhost:8085.
Step 6: Implement the following code in the client application and run it.
- class Program: ServiceRef.IStatusServieCallback
- {
- static void Main(string[] args)
- {
- Program p = new Program();
- p.CallCallBackService();
- Console.ReadKey();
- }
- public void CallCallBackService()
- {
- InstanceContext callBack = new InstanceContext(this);
- ServiceRef.StatusServieClient client = new ServiceRef.StatusServieClient(callBack);
- client.NotifyStatus();
- }
- public void Progress(int percent)
- {
- Console.WriteLine(percent + "% Comppleted.");
- }
- }
Note here. We implement the callback contract in the client and mentioned in the service instance.
Now you will see the output to the application like this.
It will print from 1 to 100. The same duplex code we will implement in another way without mentioning the
IsOneWay Property. Let us see it.
Second Way
Step 1: Implement the same service code without mentioning the IsOneWay property;
- [ServiceContract(CallbackContract = typeof (IStatusCallBack))]
- public interface IStatusServie
- {
- [OperationContract]
- void NotifyStatus();
- }
- public interface IStatusCallBack
- {
- [OperationContract]
- void Progress(int percent);
- }
Step 2: In the service implementation class mention the attribute
ServiceBehavior as mentioned below,
- [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
- public class StatusServie: IStatusServie
- {
- public void NotifyStatus()
- {
- for (int i = 1; i <= 100; i++)
- {
- Thread.Sleep(50);
- OperationContext.Current.GetCallbackChannel < IStatusCallBack > ().Progress(i);
- }
- }
- }
Step 3: There is no difference in the server host code. Just run it and capture in the client application and implement the client code with the attribute
CallbackBehavior.
- [CallbackBehavior(UseSynchronizationContext = false)]
- class Program: ServiceRef.IStatusServieCallback
- {
- static void Main(string[] args)
- {
- Program p = new Program();
- p.CallCallBackService();
- Console.ReadKey();
- }
- public void CallCallBackService()
- {
- InstanceContext callBack = new InstanceContext(this);
- ServiceRef.StatusServieClient client = new ServiceRef.StatusServieClient(callBack);
- client.NotifyStatus();
- }
- public void Progress(int percent)
- {
- Console.WriteLine(percent + "% Comppleted.");
- }
- }
Step 4: Run the application and the output will be same as previous sample.
The only difference is, if you want execute the duplex in a shorter time i.e., less than service timeout, we will use the second one. Otherwise the first way is recommended. The first way will not throw any exception, it is long time process.
That’s all about message exchange in WCF. If you have any questions about it please feel free to ask me.