Handling Messages directly

My previous samples demonstrated using ServiceModel to dispatch messages to a strongly typed message handlers. There are times when instead of having a seperate implementation for every message you will want to have a centralised message handler (often this handler is called ProcessMessage). An early version of the Peer channel system code had a message handler called ProcessMessage where the Peer channel messages were dispatched.

The Action="*" option on the OperationContract attribute is called the wildcard action it says that any value in the Headers.Action property of the message will be handled by the message handler specified by this contract, and the argument type is Message; Message is a new abstraction in the System.ServiceModel namespace that allows a developer to operate on raw messages when necessary, such as adding or retrieving Message Headers, generating or retrieving the raw Xml.

The ProcessMessageActions class defines the actions to be used in a convenient manner.

The Proxy

classHelloMesh : IProcessMessage

{

publicvoid ProcessMessage(Message message)

{

if (message.Headers.Action == ProcessMessageActions.SayAction)

{

string data = message.GetBody<string>();

Console.WriteLine(data);

}

}

}

Again the proxy does little more than delegate to the base implementation. This time the Method is called ProcessMessage and it takes a a Message as its argument. It can be used to create and read the elements of the message including headers.

The InstanceContext

This is the class that is used to handle inbound messages.It has an Implementation IProcessMessage in this case it verifies that the action matches a specific value, if so it does the work associated with that action.

classHelloMesh : IProcessMessage

{

publicvoid ProcessMessage(Message message)

{

if (message.Headers.Action == ProcessMessageActions.SayAction)

{

string data = message.GetBody<string>();

Console.WriteLine(data);

}

}

}

The Application

The application is still trivial to write, as before you create an InstanceContext for incoming messages, a proxy for outgoing messages, and then in a loop read what to send, and then use the proxy to send it.

In this case it is necessary to create a message object with the data.

The only changes necessary to the config are because we renamed the service contract and I also changed the mesh address:

To enable certain changes to be made after the application has been deployed for instance port, the endpoint and binding are usually specified in the app.config file.This is the config file for our application above.