2012-06-14 46 views
14

次のスレッドに記載されているのと同じ問題があります。エラー "このメッセージは読み取られたため操作をサポートできません"

WSDL first WCF server where client does not send SOAPAction

Iは同じスレッドに記載されている手順(下記に示す)

1)マイクロソフトWCF例をダウンロードを行います。

DispatchByBodyOperationSelector.cs WF_WCF_Samples \ WCF \拡張\ Interopの\ RouteByBody \ CS \サービスからプロジェクトに

DispatchByBodyBehaviorAttribute.csを、以下のファイルを追加します

2)(あなたのインターフェイスに次の属性を追加します。次のあなたのServiceContractに)

XmlSerializerFormat 

DispatchByBodyBehavior 

3)あなたのサービス・インターフェース

に以下を追加します。
[OperationContract(Action = "")] 

public void DoNothing() 
{ 
} 

4)私のサービスでは、WrapperNameとWrappernamespaceはすべてのメッセージでnullです。私はこれを確認するために以下の行を追加する)(DispatchByBodyBehaviorAttributeに入るとApplyDispatchBehaviorを編集する必要がありました:

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

今、私は、エラーメッセージ「それが読まれたため、このメッセージは、操作をサポートすることはできません」を取得しています。私はトレースをオンにし、スタックトレースをキャプチャしました(下記)。これがどのように解決できるかについて誰かが考えているなら、いくつかのコメントを投稿できたらと感謝します。助けてくれてありがとう!

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 
} 

答えて

28

あなたはMessageBuffer.CreateMessageを使用する必要があります。

Messageインスタンスのボディのみが消費されるか、追記することができます。 Messageインスタンスを複数回使用する場合は、 MessageBufferクラスを使用して、Message インスタンス全体をメモリに完全に格納する必要があります。私の現在のプロジェクトから

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

コード:

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のparamのためrefを追加し、新しいメッセージを返します。

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

コードを投稿していただきありがとうございます。私のシナリオでは、WCFサンプルダウンロードのクラスを再利用しています。私は以下のようにMessageBufferコードをCreateMessageCopyメソッドに入れようとしましたが、それは私のためには機能しませんでした。 – Jyina

+0

元の質問を編集し、WCFサンプルから再利用している2つのクラスを投稿しました。私はCreateMessageCopy()の既存のコードをコメントアウトし、MessageBufferを使ってメッセージを作成しようとしました。私はクライアントを走らせると、それはラインで失敗しています。 MessageBufferバッファ= message.CreateBufferedCopy(Int32.MaxValue); – Jyina

+0

この行にヒットする前にメッセージが既に読み込まれているようです。 MessageBufferコードをどこに置くべきかわかりません。何か案は?ありがとう! – Jyina

4

私もWCFサンプル(RouteByBody正確には)からのコードを使用して、非常に同様の問題があったが、それは誰にも役立ちます場合には、私はそれをここに投稿しますので、別の方法でそれを解決することができました。

状況:クライアントアプリケーション(消費者が)リリースに働くだろう 、しかし、デバッガがアタッチされたとき、それは常にエラーで失敗し「それが読み込まれているため、このメッセージは、操作をサポートすることはできません」。多くのWCFメッセージをトレースし、ログインした後

は、私のために働いた唯一の解決策は非常に単純であることが判明:

私のサービスは、IIS上でホストされ、web.configファイルの<compilation>セクションでdebug="true"とされました。

のサービスでdebug="false"に変更すると、すべての問題が修正されました。 (「それがコピーされているため、このメッセージは、操作をサポートすることはできません」。それはあなたを与えるだろうエラー)

+0

しかし、どのようにデバッグすることができますか? –

+0

これは私たちのために働いています。デバッガをプロセスから切り離すと、メッセージが送信されます。デバッガをアタッチすると、InvalidOperationExceptionが発生します。「メッセージは読み込まれているため、この操作をサポートできません。さらに、エラーは、サービスに対して 'DispatchByBodyBehavior'が使用されている場合にのみ発生するようです。 – knittl

+0

うまくいった!私はあなたを愛している – MirlvsMaximvs

2

ドミトリーHarnitskiの答えは、あなたがサービスをデバッグしている場合は動作しません

これでもデバッグモードで動作します:

XmlDictionaryReader GetReader(ref Message message) 
{ 
    MessageBuffer buffer = message.CreateBufferedCopy(Int32.MaxValue); 
    message = buffer.CreateMessage(); 
    newMessage = buffer.CreateMessage(); 
    XmlDictionaryReader rv = buffer.CreateMessage().GetReaderAtBodyContents(); 
    buffer.Close(); 
    return rv; 
} 

static System.ServiceModel.Channels.Message newMessage = null; 
static System.ServiceModel.Channels.Message lastMessage = null; 

public string SelectOperation(ref System.ServiceModel.Channels.Message message) 
{ 
    try 
    { 
     if(message == lastMessage) 
      message = newMessage; 

     XmlDictionaryReader bodyReader = GetReader(ref message); 

     lastMessage = message; 

     XmlQualifiedName lookupQName = new XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI); 
     if (dispatchDictionary.ContainsKey(lookupQName)) 
     { 
      return dispatchDictionary[lookupQName]; 
     } 
     else 
     { 
      return null; 
     } 
    } 
    catch(Exception ex) 
    { 
     throw ex; 
    } 
} 
関連する問題