强制WCF在客户端代理中创建XML命名空间别名

4

我使用“添加服务引用”功能来创建一个指向外部 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客户端的默认行为是将命名空间定义为默认命名空间。我已经搜遍了各种配置/修饰的解决方案,但没有找到。如果没有配置解决方案,我将不得不检查并修改每个序列化后的SOAP消息。#无聊。
这里有一个简单的解决方案吗?

感谢您的回复。这似乎可能有效。它要求手动修改所有消息契约。在此API中有很多这样的契约。我最终找到了一个更简单的解决方案。再次感谢。 - Walter Pinson
1个回答

3
这个问题的解决方案是创建一个自定义的MessageInspector (通过IClientMessageInspector),来检查和修改WCF客户端代理生成的SOAP消息,在将它们发送到网络之前。这个解决方案的基础在Steven Cheng的文章中有所阐述,"[WCF] How to modify WCF message via custom MessageInspector",Kirk Evan的文章提供了更多背景信息,"Modify Message Content with WCF"
我使用了Steven文章中的代码来连接自定义的MessageInspector基础设施。然后我修改了他的Transformf2()方法,该方法仅对SOAP消息的部分进行操作,以适应我的特定需求。在我的情况下,正如原始问题中所描述的那样,我需要为我的目标Web服务XML命名空间定义并使用别名xmlns="http://tempuri.org"
为了做到这一点,我必须
  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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接