Message Exchange Patterns (MEP) in WCF :
MEPs describe the protocol of message exchanges a consumer must engage in to converse properly with the service. For instance, if a consumer sends a message, it needs to know whether it should expect a message back or whether simply sending the request is enough.
Further, can the consumer expect unsolicited messages back from the service?
WCF supports the following three MEPs, each of which is covered in more detail in this section:
- Request/Response
- OneWay
- Duplex
Request/Response :
This is by far the most common MEP and very little has to be done to set it up because the default value for the Is One Way property of Operation Contract Attribute is false.
Thus, as long as you don’t have IsOneWay set to true, and you are not in a Duplex channel setting, you are using Request/Response.
Note that it doesn’t even necessarily mean that you have a non-void return type. That is to say, even with a void return type, if you are using Request/Response, then a response message is still going back to the consumer when the operation is called; it just would have an empty SOAP body.
Also, this two-way communication channel enables the service
to issue faults (if anything goes wrong), return transaction contexts, or both.
In the following code sample, both operations are configured to use the Request/Response MEP:
[ServiceContract()]
public interface ILogisticsService
{
[OperationContract()]
WorkOrderAcknowledgement SubmitWorkOrder(WorkOrder workOrder);
[OperationContract()]
void CancelWorkOrder(int workOrderNumber);
}
Finally, all WCF bindings except the MSMQ-based bindings support the Request/Response MEP.
OneWay :
Sometimes, you simply want to send a message off to a service and have it trigger some sort of business logic, and you aren’t in fact interested in receiving anything back from the service.
In such cases, you might want to use the OneWay MEP, that is, have the consumer simply send one-way messages into the service endpoint without any responses back from the service.
ThisMEP is declared by setting the Is OneWay property on the OperationContractAttribute to true.
The following shows an example of this:
[ServiceContract()]
public interface ILogisticsService
{
[OperationContract(IsOneWay=true)]
void CancelWorkOrder(int workOrderNumber);
}
However, you must keep the following points in mind when considering whether the OneWay MEP is the right choice for you:
- It cannot be used in conjunction with the FaultContract attribute because for a service to issue faults, it must have a two-way channel of some form, which is not the case with one-way messaging. Nor can it return transaction contexts.
- It can be dangerous just to send off a one-way message and not have some assurances that it arrived and was processed. So, with that in mind, if an MSMQ binding is feasible in your environment, you might want to use OneWay messaging only when you can couple it with queued message delivery.
- Note also that, if you want queued message delivery, the OneWay MEP is your only choice, at least as far as the WCF infrastructure is concerned.
- Also be aware that it does not conform to the asynchronous, send-and-forget semantics that one might think it does, given the name “one-way.” In other words, given the oneway nature of the channel, one might think that as soon as the consumer sends the message, it is processed asynchronously from that point on and the client is free to do other things.
Duplex :
The Duplex MEP is a two-way message channel whose usage might be applicable in either of these two situations:
- The consumer sends a message to the service to initiate some longer-running processing and then subsequently requires notification back from the service, confirming that the requested processing has been done.
- The consumer needs to be able to receive unsolicited messages from the service.
Because there are two Service contracts to consider in a Duplex MEP scenario, namely the Service contract and the Callback contract, this MEP is declared by associating the Callback contract with the Service contract.
This association is done through the CallbackContract property
of the ServiceContractAttribute that is adorning the service that needs to be capable of calling back to a consumer.
For an example of this, consider a simple “Hello World” application, this time where a consumer sends a one-way message to a greeting service, and at some point after that, the service calls back to the consumer and says, “I have processed your greeting request and here it is; I am calling you back with it now.”
The following code shows not only the Service
contract, the Callback contract, and how they are associated but also how the service implementation (that is, the service type) uses the OperationContext to ask for a reference to the Callback contract, thereby enabling the service to call back to the consumer.
Here is the code:
[ServiceContract]
interface IGreetingHandler
{
[OperationContract(IsOneWay = true)]
void GreetingProduced(string greeting);
}
[ServiceContract(CallbackContract =
typeof(IGreetingHandler))]
interface IGreetingService
{
[OperationContract(IsOneWay = true)]
void RequestGreeting(string name);
}
[ServiceBehavior(InstanceContextMode =
InstanceContextMode.PerSession)]
class GreetingService : IGreetingService
{
public void RequestGreeting(string name)
{
Console.WriteLine("In Service.Greet");
IGreetingHandler callbackHandler =
OperationContext.Current.GetCallbackChannel<IGreetingHandler>();
callbackHandler.GreetingProduced("Hello " + name);
}
}