错误“此消息无法支持该操作,因为它已被读取" [英] Error "This message cannot support the operation because it has been read"

查看:30
本文介绍了错误“此消息无法支持该操作,因为它已被读取"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了以下线程中列出的相同问题.

I have the same problem that is listed in the following thread.

WSDL 第一个 WCF 服务器在哪里客户端不发送 SOAPAction

我执行了在同一线程中列出的步骤(也如下所示)

I performed the steps that are listed in the same thread (also shown below)

1) 下载 Microsoft WCF 示例.将以下文件从 WF_WCF_Samples\WCF\Extensibility\Interop\RouteByBody\CS\service

1) Download the Microsoft WCF examples. Add the following files to your project from WF_WCF_Samples\WCF\Extensibility\Interop\RouteByBody\CS\service

DispatchByBodyOperationSelector.cs

DispatchByBodyOperationSelector.cs

DispatchByBodyBehaviorAttribute.cs

DispatchByBodyBehaviorAttribute.cs

2) 将以下属性添加到您的界面(在您的 ServiceContract 旁边)

2) Add the following attributes to your interface (next to your ServiceContract)

XmlSerializerFormat

DispatchByBodyBehavior

3) 将以下内容添加到您的服务接口

3) Add the following to your service interface

[OperationContract(Action = "")]

public void DoNothing()
{
}

4) 对于我的服务,所有消息的 WrapperName 和 Wrappernamespace 都为空.我必须进入 DispatchByBodyBehaviorAttribute 并编辑 ApplyDispatchBehavior() 以添加以下行来检查:

4) For my service the WrapperName and Wrappernamespace are null for all messages. I had to go into DispatchByBodyBehaviorAttribute and edit ApplyDispatchBehavior() to add the following lines to check for this:

 if (qname.IsEmpty) {
     qname = new XmlQualifiedName(operationDescription.Messages[0].Body.Parts[0].Name, operationDescription.Messages[0].Body.Parts[0].Namespace);
 }

现在,我收到一条错误消息此消息无法支持该操作,因为它已被读取".我打开了跟踪并捕获了堆栈跟踪(如下).如果有人对如何解决此问题有任何想法,如果您能发表一些评论,我将不胜感激.感谢您的帮助!

Now, I am getting an error message "This message cannot support the operation because it has been read". I turned the tracing on and captured the stack trace (below). If anyone has any idea on how this can be resolved, I appreciate if you could post some comments. Thanks for any help!

at System.ServiceModel.Channels.Message.GetReaderAtBodyContents()
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, Action callback)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>


class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
{
    Dictionary<XmlQualifiedName, string> dispatchDictionary;

    public DispatchByBodyElementOperationSelector(Dictionary<XmlQualifiedName, string> dispatchDictionary)
    {
        this.dispatchDictionary = dispatchDictionary;            
    }

    #region IDispatchOperationSelector Members

    private Message CreateMessageCopy(Message message, XmlDictionaryReader body)
    {
        //Message copy = Message.CreateMessage(message.Version, message.Headers.Action, body);
        //copy.Headers.CopyHeaderFrom(message, 0);
        //copy.Properties.CopyProperties(message.Properties);
        //return copy;    

        MessageBuffer buffer = message.CreateBufferedCopy(Int32.MaxValue);
        Message copy = buffer.CreateMessage();
        buffer.Close();
        copy.Headers.CopyHeaderFrom(message, 0);
        copy.Properties.CopyProperties(message.Properties);

        return copy;
    }

    public string SelectOperation(ref System.ServiceModel.Channels.Message message)
    {
        XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();

        XmlQualifiedName lookupQName = new XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);
        message = CreateMessageCopy(message,bodyReader);
        if (dispatchDictionary.ContainsKey(lookupQName))
        {
            return dispatchDictionary[lookupQName];
        }
        else
        {
            return null;
        }
    }

    #endregion
}

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]
sealed class DispatchByBodyBehaviorAttribute : Attribute, IContractBehavior
{
    #region IContractBehavior Members

    public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
        // no binding parameters need to be set here
        return;
    }

    public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
        // this is a dispatch-side behavior which doesn't require
        // any action on the client
        return;
    }

    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
    {
        // We iterate over the operation descriptions in the contract and
        // record the QName of the request body child element and corresponding operation name
        // to the dictionary to be used for dispatch 
        Dictionary<XmlQualifiedName,string> dispatchDictionary = new Dictionary<XmlQualifiedName,string>();
        foreach( OperationDescription operationDescription in contractDescription.Operations )
        {
            XmlQualifiedName qname =
                new XmlQualifiedName(operationDescription.Messages[0].Body.WrapperName, operationDescription.Messages[0].Body.WrapperNamespace);




            if (qname.IsEmpty)
            {
                qname = new XmlQualifiedName(operationDescription.Messages[0].Body.Parts[0].Name, operationDescription.Messages[0].Body.Parts[0].Namespace);
            }

            dispatchDictionary.Add(qname, operationDescription.Name);                
        }

        // Lastly, we create and assign and instance of our operation selector that
        // gets the dispatch dictionary we've just created.
        dispatchRuntime.OperationSelector = 
            new DispatchByBodyElementOperationSelector(dispatchDictionary);
    }

    public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
    {
        // 
    }

    #endregion
}

推荐答案

你应该使用 MessageBuffer.CreateMessage:

Message 实例的主体只能被消费或写入一次.如果您希望多次使用 Message 实例,您应该使用 MessageBuffer 类来完全存储整个 Message实例到内存中.

The body of a Message instance can only be consumed or written once. If you wish to consume a Message instance more than once, you should use the MessageBuffer class to completely store an entire Message instance into memory.

http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.messagebuffer.aspx

来自我当前项目的代码:

Code from my current project:

public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
    MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
    reply = buffer.CreateMessage();
    Message m = buffer.CreateMessage();
    LogMessage(m, " Response => ");
}

Message参数添加ref并返回新消息.

Add ref for Message param and return new message.

 private Message CreateMessageCopy(ref Message message, XmlDictionaryReader body)
{
...
   message = buffer.CreateMessage();

这篇关于错误“此消息无法支持该操作,因为它已被读取"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆