I am trying to implement a very basic reliable message state handling system to provide improved reliability in my Silverlight to WCF server communications.
I have taken the route of introducing a custom message header into the SOAP request that contains an incrementing integer as a message ID. The idea is that when I receive a request at the WCF server, I want to check the message ID. If the ID is > the last ID, then I simply execute the request and AFTER the request, I cache a copy of the result along with the new ID.
If the ID is == the lastID, I assume the client never received my message and I want to simply return the cache'd response object instead of re-processing the request. I have written a MessageInspector Behavior object that I inject into the WCF Endpoint behaviors. This object implements the IDispatchMessageInspector, which has 2 methods:
object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Get the incoming message headers and get the messageId
var idx = request.Headers.FindHeader("ClientRequestId", "");
if (idx >= 0)
{
var requestHeader = request.Headers[idx];
int requestId = 0;
if (Int32.TryParse(requestHeader.ToString(), out requestId))
{
int lastRequest = myCache.GetLastId();
if (requestId <= lastRequest)
{
// @TODO - Send back the saved message
var reply = myCache.GetLastResponse();
if (reply != null)
{
/// ERK -- > Woops, how do I override the service
/// and make the reply here?
}
}
myCache.SetLastId(requestId);
}
}
return null;
}
void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
var requestId = myCache.GetLastId();
if (requestId > 0)
{
myCache.SetLastResponse(reply);
}
}
Well, the problem I ran into should be obvious... The AfterReceiveRequest return value (object) is the value passed to BeforeSendReply as "correlatedState". NOT, as I originally anticipated, the new return value for the request. The question is, can I stop the message from processing to the service at this location and return a 'cached' response?
Actually the better version of this question: is this the appropriate 'injection' location to handle the caching and response tracking? If not, where would be the "approved ms" or better way of accomplishing this request tracking and recovery?
thanks.
-Jeff