WCF design challenge - recording and replaying WCF communication

Hi!

SETTING: I have a WCF service that offers client applications the choice between WsDualHttpbinding and NetTcpBinding. It is a singleton service (InstanceContextMode.Single) running a state-machine. The service is always initialized the same way during startup, so that it's state is predictable until a client has connected. The only thing that affects the state-machine is time and client requests (it is a simulator).

TASK 1: I want to insert a layer in the WCF stack that time stamp and records all messages (requests) from the client(s) and save them to file. The request should be executed normally.

TASK 2: Upon a certain WCF operation call (Let us call it "ReplaySimulation()"), I want to reset the state-machine and read back and execute all the messages from file (typically this can be used to debrief a simulator session).

QUESTION: I have looked at the WCF examples and found that it is probably many alternative ways to solve this. Cue words areMessageFilter,IDispatchMessageInspector,IDispatchOperationSelector, IDispatchMessageFormatter etc. Anyone with an idea/suggestion on how to approach this?

Kind regards

Dag

[1823 byte] By [DagSanna] at [2008-1-8]
# 1
I think you can go for an IDispatchMessageInspector in both cases.
ChristianWeyer at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 2

Thanks for your reply Christian! It's weekend and I did not expect an answer that soon. I guess you are addicted, as I can feel I'm about to be...

IDispatchMessageInspector is my favourite too, although IDispatchOperationSelector also seams to be suited. Both provide easy access to the unformatted message. Time stamping and logging the message should be fairly plain foreward.

The tricky part will be re-playing the messages. I can't find a way of invoking many new operations from within the AfterReceiveRequest() method. I can use the InstanceContext.GetServiceInstance() to get a reference to the service object, and then use reflection to validate methods and arguments before I invoke the operations. However, WCF already does all this stuff. How can I route the restored messages through a path as if they were received on the network?

As a last resort, I can always instantiate a client within the service that connets to the service itself, sending message by message.

The thing is, it seams that there are almost no limitations to what is possible with WCF. I am sure that there is an elegant solution to this, but I can't find it...

Best regards

Dag

DagSanna at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 3

Still hoping for more input from you guys out there. Sure there must be someone that know how to do this.

To test the concept I have implemented a custom Attribute class that also inherit IServiceBehaviour. The ApplyDispatchBehaviour() method look like this:

Code Snippet

public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)

{

Dictionary<XmlQualifiedName, OperationDescription> dispatchDictionary = new Dictionary<XmlQualifiedName, OperationDescription>();

foreach (ServiceEndpoint endpoint in serviceHostBase.Description.Endpoints)

{

foreach (OperationDescription operationDescription in endpoint.Contract.Operations)

{

XmlQualifiedName qname = new XmlQualifiedName( operationDescription.Messages[0].Body.WrapperName, operationDescription.Messages[0].Body.WrapperNamespace);

if (!dispatchDictionary.ContainsKey(qname))

dispatchDictionary.Add(qname, operationDescription);

}

}

SaveRestoreExtension extension = new SaveRestoreExtension(dispatchDictionary);

foreach (ChannelDispatcherBase dispatcherBase in serviceHostBase.ChannelDispatchers)

{

ChannelDispatcher dispatcher = dispatcherBase as ChannelDispatcher;

foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)

{

endpointDispatcher.DispatchRuntime.MessageInspectors.Add(extension);

}

}

}

and the SaveRestoreExtension class of course inherits IDispatchMessageInspector. Its AfterReceiveRequest() method look like this:

Code Snippet

object IDispatchMessageInspector.AfterReceiveRequest(

ref Message request,

IClientChannel channel,

InstanceContext instanceContext)

{

// Lookup operation description

System.Xml.XmlDictionaryReader bodyReader = request.GetReaderAtBodyContents();

XmlQualifiedName lookupQName = new XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);

request = CreateMessageCopy(request, bodyReader);

if (!dispatchDictionary.ContainsKey(lookupQName))

{

return null;

}

// Extract operation name and parameter info

OperationDescription operationDescription = dispatchDictionary[lookupQName];

string operationName = operationDescription.Name;

ParameterInfo[] parameterInfos = operationDescription.SyncMethod.GetParameters();

int numberOfParameters = parameterInfos.Length;

// Deserialize parameters

object[] parameters = null;

if (0 < numberOfParameters)

{

parameters = new object[numberOfParameters];

bodyReader.MoveToContent();

bodyReader.ReadStartElement(operationName);

for (int i = 0; i < parameterInfos.Length; ++i)

{

DataContractSerializer ser = new DataContractSerializer(parameterInfos[i].ParameterType);

parameters[i] = ser.ReadObject(bodyReader, true);

}

bodyReader.ReadEndElement();

bodyReader.Close();

}

// Invoke operation (just to test the concept - the method will also be

// invoked upon exit of this method)

object serviceInstance = instanceContext.GetServiceInstance();

operationDescription.SyncMethod.Invoke(serviceInstance, parameters);

return null;

}

Can't figure out how the deserializing of parameters should be performed though. The code above gives an exception as the DataContractSerializer does not find the correct data type. Does anyone know how to deserialize a WCF Message body containing a serialized method call into an array of objects containing the method arguments? I'll be very grateful for a little example!

I hope the invokation part on the end should work. At least it seams to work for parameterless methods...

Dag

DagSanna at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...

Visual Studio Orcas

Site Classified