4

WCF サービスでのメッセージ解析に問題があります。サーバー側で WCF アプリケーションを実行しました。別の会社から次のような HTTP POST リクエストが送られてきます。

POST /telemetry/telemetryWebService HTTP/1.1
Host: 192.168.0.160:12123
Content-Length: 15870
Expect: 100-continue
Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security> ... </wsse:Security>
  </soapenv:Header>
<soapenv:Body>
...
</soapenv:Body>
</soapenv:Envelope>

この HTTP リクエストで、2 つの重要なヘッダー ( Soap ActionContent-type ) が欠落していることがわかります。これが、私のサービスがこのリクエストを正しく処理できない理由です。

処理が開始されるまでリクエストをキャッチし、これらのヘッダーを手動で追加する必要があります。

私はすでにIDispatchMessageInspectorを試しましたが、結果はありません。

4

2 に答える 2

2

SOAP メッセージを操作する場合、サーバー側でのディスパッチは SOAP アクション ヘッダーに従って行われます。このヘッダーは、メッセージを処理する対応するメソッドをディスパッチャに指示します。

SOAP アクションが空または無効な場合があります (Java 相互運用性)。

IDispatchOperationSelector を実装するのが最善の方法だと思います。これにより、サーバーが着信メッセージを操作に割り当てるデフォルトの方法をオーバーライドできます。

次のサンプルでは、​​ディスパッチャーは、SOAP 本文内の最初の要素の名前を、処理のためにメッセージが転送される操作名にマップします。

 public class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
    {
        #region fields

        private const string c_default = "default";
        readonly Dictionary<string, string> m_dispatchDictionary;

        #endregion

        #region constructor

        public DispatchByBodyElementOperationSelector(Dictionary<string, string> dispatchDictionary)
        {
            m_dispatchDictionary = dispatchDictionary;
            Debug.Assert(dispatchDictionary.ContainsKey(c_default), "dispatcher dictionary must contain a default value");
        }

        #endregion

        public string SelectOperation(ref Message message)
        {
            string operationName = null;
            var bodyReader = message.GetReaderAtBodyContents();
            var lookupQName = new
               XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);

            // Since when accessing the message body the messageis marked as "read"
            // the operation selector creates a copy of the incoming message 
            message = CommunicationUtilities.CreateMessageCopy(message, bodyReader);

            if (m_dispatchDictionary.TryGetValue(lookupQName.Name, out operationName))
            {
                return operationName;
            }
            return m_dispatchDictionary[c_default];
        }
    }
于 2012-10-01T07:26:35.853 に答える
0

皆さん、ありがとうございました。

1) 独自のカスタム メッセージ エンコーダーを作成する必要があります。デフォルトで Content-type を作成できます。ここで例を挙げて読むことができます。

2) SoapActionなしでメッセージをスキップする必要があるため、カスタム メッセージ フィルターを作成する必要があります。

public class CustomFilter : MessageFilter
{
    private int minSize;
    private int maxSize;
    public CustomFilter()
        : base()
    {

    }
    public CustomFilter(string paramlist)
        : base()
    {
        string[] sizes = paramlist.Split(new char[1] { ',' });
        minSize = Convert.ToInt32(sizes[0]);
        maxSize = Convert.ToInt32(sizes[1]);
    }
    public override bool Match(System.ServiceModel.Channels.Message message)
    {
        return true;
    }
    public override bool Match(MessageBuffer buffer)
    {
        return true;
    }
}

3)受信メッセージを操作に割り当てるためのカスタム メッセージ セレクターを作成する必要があります。Cyber​​maxsの例は非常に優れています。

于 2012-10-08T07:32:43.750 に答える