为SilverLight实现WCF可靠服务的自己设计的问题(basicHttpBinding)

时间:2022-01-17 09:48:55

I am trying to implement a very basic reliable message state handling system to provide improved reliability in my Silverlight to WCF server communications.

我正在尝试实现一个非常基本的可靠消息状态处理系统,以提高Silverlight到WCF服务器通信的可靠性。

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.

我已经采用了将自定义消息头引入SOAP请求的路径,该SOAP请求包含一个递增整数作为消息ID。我的想法是,当我在WCF服务器上收到请求时,我想检查消息ID。如果ID是>最后一个ID,那么我只是执行请求并在请求之后,我将结果的副本与新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:

如果ID是== lastID,我假设客户端从未收到过我的消息,我想简单地返回缓存响应对象而不是重新处理请求。我编写了一个MessageInspector Behavior对象,我将其注入到WCF Endpoint行为中。该对象实现了IDispatchMessageInspector,它有两个方法:

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?

好吧,我遇到的问题应该是显而易见的...... AfterReceiveRequest返回值(对象)是传递给BeforeSendReply的值为“correlationState”。不,正如我最初预期的那样,请求的新返回值。问题是,我可以阻止消息处理到此位置的服务并返回“缓存”响应吗?

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?

实际上这个问题的更好版本是:这是处理缓存和响应跟踪的适当“注入”位置吗?如果没有,那么“批准ms”或更好的方式来完成此请求跟踪和恢复?

thanks.

-Jeff

2 个解决方案

#1


i think you're trying to re-invent the wheel slightly here. WCF has Reliable Messaging that is designed to ensure message delivery already. I'd try that, unless that is you don't want to use it for a specific reason?

我想你在这里试图重新发明*。 WCF具有Reliable Messaging,旨在确保消息传递。我试试,除非你不想出于特定原因使用它?

#2


After much trial and tribulation, I found a solution to my problem that, if not elegant, is functional.

经过多次试验和磨难,我找到了解决我的问题的方法,如果不是很优雅,那就是功能性的。

In order to bypass the call to the service endpoint when I detect a duplicate service request, I simply throw a FaultException. Then in the BeforeSendReply method, I check to see if replay.IsFault and then if the fault is the specific fault code I threw in AfterReceiveRequest. If so, i return the cached copy of the message response. The FaultException mechanism is what I need to use to bypass the the service call.

为了在检测到重复的服务请求时绕过对服务端点的调用,我只是抛出一个FaultException。然后在BeforeSendReply方法中,我检查是否重播.IsFault然后如果故障是我在AfterReceiveRequest中抛出的特定故障代码。如果是这样,我将返回消息响应的缓存副本。我需要使用FaultException机制来绕过服务调用。

If anyone wants full working code for this solution, drop a note here and I'll post my final code after I complete final debug and unit test.

如果有人想要这个解决方案的完整工作代码,请在此处删除一个注释,并在完成最终调试和单元测试后发布我的最终代码。

-Jeff

#1


i think you're trying to re-invent the wheel slightly here. WCF has Reliable Messaging that is designed to ensure message delivery already. I'd try that, unless that is you don't want to use it for a specific reason?

我想你在这里试图重新发明*。 WCF具有Reliable Messaging,旨在确保消息传递。我试试,除非你不想出于特定原因使用它?

#2


After much trial and tribulation, I found a solution to my problem that, if not elegant, is functional.

经过多次试验和磨难,我找到了解决我的问题的方法,如果不是很优雅,那就是功能性的。

In order to bypass the call to the service endpoint when I detect a duplicate service request, I simply throw a FaultException. Then in the BeforeSendReply method, I check to see if replay.IsFault and then if the fault is the specific fault code I threw in AfterReceiveRequest. If so, i return the cached copy of the message response. The FaultException mechanism is what I need to use to bypass the the service call.

为了在检测到重复的服务请求时绕过对服务端点的调用,我只是抛出一个FaultException。然后在BeforeSendReply方法中,我检查是否重播.IsFault然后如果故障是我在AfterReceiveRequest中抛出的特定故障代码。如果是这样,我将返回消息响应的缓存副本。我需要使用FaultException机制来绕过服务调用。

If anyone wants full working code for this solution, drop a note here and I'll post my final code after I complete final debug and unit test.

如果有人想要这个解决方案的完整工作代码,请在此处删除一个注释,并在完成最终调试和单元测试后发布我的最终代码。

-Jeff