4

Add Service Reference 機能を使用して、外部 Web サービスへのプロキシを作成しました。

既定では、WCF クライアントは、メッセージ本文に次のような名前空間の装飾が含まれる SOAP メッセージを生成します。

  <s:Body>
    <BankingTransaction xmlns="http://tempuri.org/">
      <amount>0</amount>
    </BankingTransaction>
  </s:Body>

代わりに、メッセージ本文を次のようにする必要があります

  <s:Body>
    <bb:BankingTransaction xmlns:bb="http://tempuri.org/">
      <amount>0</amount>
    </bb:BankingTransaction>
  </s:Body>

違いは、"bb" xml 名前空間エイリアスです。利用しようとしている Web サービスでは、メッセージ ペイロードの xml 名前空間にエイリアスを設定する必要があります。また、WCF クライアントの既定の動作は、名前空間を DEFAULT 名前空間として定義することです。この問題の構成/装飾ソリューションを高低で検索しましたが、見つかりませんでした。構成ソリューションがなければ、シリアル化された後に各 SOAP メッセージを調べて変更する必要があります。#ラメ。

ここに簡単な解決策はありますか?

4

1 に答える 1

3

この問題の解決策は、 ( IClientMessageInspectorを介して)カスタム MessageInspectorを作成し、ネットワーク経由で送信する前に、WCF クライアント プロキシが生成する SOAP メッセージを検査および変更することです。このソリューションの基礎は、Steven Cheng の投稿「[WCF] カスタム MessageInspector を介して WCF メッセージを変更する方法」で明確にされており、Kirk Evan の投稿「WCF を使用してメッセージ コンテンツを変更する」からの詳細な背景が示されています。

カスタム MessageInspector インフラストラクチャを接続するために、Steven の投稿のコードを使用しました。次に、彼の Transformf2() メソッドを変更しました。このメソッド<Body>は、SOAP メッセージの一部のみを処理するもので、特定のニーズに合わせて変更しました。私の場合、元の質問で説明したようにxmlns="http://tempuri.org"、上記のターゲット Web サービス XML 名前空間のエイリアスを定義して使用する必要がありました。

これを行うには、私がしなければならない

  1. 操作ノード への参照を取得します<BankingTransaction>。これは常に の最初の (そして唯一の) 子になります。<Body>
  2. デフォルトの名前空間をターゲット名前空間に設定する属性を削除します
  3. ノードのプレフィックス (名前空間エイリアス) を設定します

これを行う変更された Transform2() コードは次のとおりです。

   private static Message Transform(Message oldMessage)
    {
        //load the old message into XML
        var msgbuf = oldMessage.CreateBufferedCopy(int.MaxValue);

        var tmpMessage = msgbuf.CreateMessage();
        var xdr = tmpMessage.GetReaderAtBodyContents();

        var xdoc = new XmlDocument();
        xdoc.Load(xdr);
        xdr.Close();

        // We are making an assumption that the Operation element is the
        // first child element of the Body element
        var targetNodes = xdoc.SelectNodes("./*");

        // There should be only one Operation element
        var node = (null != targetNodes) ? targetNodes[0] : null;

        if (null != node)
        {
            if(null != node.Attributes) node.Attributes.RemoveNamedItem("xmlns");
            node.Prefix = "bb";
        }

        var ms = new MemoryStream();
        var xw = XmlWriter.Create(ms);
        xdoc.Save(xw);
        xw.Flush();
        xw.Close();

        ms.Position = 0;
        var xr = XmlReader.Create(ms);

        //create new message from modified XML document
        var newMessage = Message.CreateMessage(oldMessage.Version, null, xr);
        newMessage.Headers.CopyHeadersFrom(oldMessage);
        newMessage.Properties.CopyProperties(oldMessage.Properties);

        return newMessage;
    }
}
于 2013-02-25T15:55:55.627 に答える