Monday, September 8, 2008

How to implement a generic WCF message interceptor:

In a changing business environment and business processes; changes affects not only the entire work force, cooperate partners, the way businesses are done and of course our tools that makes our work life better. We are left with the choice of ensuring that our legacy or existing system inter-operate well into our new ways of life and they deliver the expected result that yields expected ROI. Because for today's business to survive, we need to carry along with us our efforts of yesterday, we need to have decoupling in mind when we are integrating services for a wider business sector. These were the thoughts in Microsoft when it first launched the framework (WCF) that shook the whole distributed computing industry.

Windows Communication Foundation is a Microsoft initiative of building Service Oriented Applications that leverages yesterdays and todays technologies, in fact it complements existing distributed technologies. The WCF (Windows Communication Foundation) infrastructure is built into .NET 3.0/3.5 and can be leveraged for different kinds of communication types/endpoint, that ranges from Message Queue, TCP communication, standard webservices, service based webservices. The most commonly used approach is the Service based where you can host it as .asmx or .svc.

In a typical WCF implementation, we have the following :

  • Datacontract. Represents the data that will be wired from one endpoint to the other. Any CLR compliant type marked as datacontract can be serialized and wired over the communication protocol.
  • Message Contract : Think of messages as envelopes, that wraps up our data/data contracts over the wire. Our message have a body and header section. It is analogous to SOAP envelope, in-fact it is converted to a SOAP envelope when the message serialization begins at runtime.
  • Service Contract : Here is the interface that is marked [ServiceContract] which can be called remotely by clients of the service. In our service, we will implement this interface and provide business functionalities that clients will consume and call remotely. Services can expose one - To - Many endpoints (Listener point), and more than one service operations can be exposed by an endpoint.
  • Service Endpoint : Think of an endpoint as message gateways for services that are hosted. A service can be configured to listen for request in different endpoints. A service Endpoint has an Address, a Binding, and a Contract.
  1. An address that describes the location where messages can be sent.
  2. A Binding specifies the type of communication that an endpoint can make using protocols such as HTTP, TCP, MSMQ and security requirements such as SSL, WS-Security etc.
  3. Contract : The binding contract are sets of messages that defines sets of operations that can be accessed by the service clients.

Message Oriented Concept In WCF
I mentioned above that the service contract defines operations that are used to send request and response messages over the transport layer defined by the service endpoint. In a simple client/server architecture, messages can be coupled between sending interface and the receiving end. That is there is a stub and skeleton relationship between the service and the consumers. Although, there is noting wrong in the stub and skeleton approach, that is a client\consumer keeps a stub or proxy of the services that it can talk to. This means when a service changes the client is regenerated using svcutil.exe tool for re-generation of the service stubs.

In an ever changing world of buisiness, we need to build services with simplycity in mind, conformance to changes. How do we allow a generic communication between our service and the rest of the world. Thinking about generic-ability of our services, we need to create an interceptor service that sits in between our clients and services, although the contract binding will be between our client and service, but the address binding will be between our client and the interceptor.

Having understood the basics of the WCF fundamentals, we need to now understand how to pass messages in a generic context.

The Interceptor Pattern
This pattern came into mind when i fell deeply into a WCF scenario that requires changing of service messages or re-delegating a service request to other service other than the requested one. Also you can use this pattern to achieve load-balancing amongst services.

One of the reason's why you might want to use an interceptor pattern is the following :
  • Expose a single entry to the entire world with the interceptor/facade.
  • Do load - balancing with the interceptor.
  • Expose a REST (Representational State Transfer) to the world while your back - end service supports WCF semantics, so you need an interceptor to bridge the gap between the pure xml and soap messages required by the WCF services.
  • Manipulating/ validation on the facade/interceptor end before delegating to the actual service.
  • A form of clean architecture design pattern
  • Securability as single entry is used as the entry point. Security is focused on that single entry instead of all
  • etc
The list above goes on and on without end, and there isnt a limit to what our services mediator can achieve. So how do we do the coding (Good Question) : so lets start with defining our service contract :


[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface IRequestDispatcher
{
[OperationContract(IsOneWay = false, Action = "*", ReplyAction = "*")]
System.ServiceModel.Channels.Message ProcessMessage(System.ServiceModel.Channels.Message message);
}


Note the ProcessMessage operation in our IRequestDispatcher contract, this operation accepts and return a Message from the System.ServiceModel.Channels namespaces and it is the only operation that we need to generically or intercept message calls from client and server.

You will also note that the ProcessMessage method is decorated with [OperationContract(IsOneWay = false, Action = "*", ReplyAction = "*")]. This is to tell our service that our method (ProcessMessage) can process any operation call from different client, by marking it Action = "*" and ReplyAction = "*" . This is the basic of our interceptor strategy.

The Big Picture
Lets have a simple picture of what we want to achieve. We have two WCF services one accepts a string and returns a string, the other accepts an object and returns a string. This services are our back office operations that is open to services that are within our domain. Assuming we want to expose this services to the entire world, we will end up exposing two services. So, if any of the services changes, that means the entire world will have to change with it, this is quite burden some. So, instead of exposing the two services, we have to expose only one service that is generic to all other services, and this service communicates in REST - FUL manner (pure XML and no soap messaging).

Lets define the big picture of