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

C# 强制WCF在客户端代理中创建xml命名空间别名,c#,wcf,xml-serialization,wcf-client,C#,Wcf,Xml Serialization,Wcf Client,我使用添加服务引用功能创建了一个到外部web服务的代理 默认情况下,WCF客户端生成SOAP消息,其中消息体具有如下名称空间装饰: <s:Body> <BankingTransaction xmlns="http://tempuri.org/"> <amount>0</amount> </BankingTransaction> </s:Body> 0 我需要消息体看起来像这样 &

我使用添加服务引用功能创建了一个到外部web服务的代理

默认情况下,WCF客户端生成SOAP消息,其中消息体具有如下名称空间装饰:

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

0
我需要消息体看起来像这样

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

0
区别在于“bb”xml名称空间别名。我试图使用的web服务要求消息负载的xml命名空间具有别名。WCF客户端的默认行为是将名称空间定义为默认名称空间。我到处寻找这个问题的配置/装饰解决方案,但没有找到。除非有配置解决方案,否则在序列化每个SOAP消息之后,我必须对其进行检查和更改#瘸子


这里有一个简单的解决方案吗?

这个问题的解决方案是创建一个自定义MessageInspector(通过IClientMessageInspector)来检查和更改WCF客户端代理生成的SOAP消息,然后再通过网络发送这些消息。这一解决方案的基础在Steven Cheng的文章中阐述,并从Kirk Evan的文章中进一步介绍

我使用Steven帖子中的代码连接自定义MessageInspector基础结构。然后我修改了他的Transformf2()方法,该方法只对SOAP消息的
部分进行操作,以满足我的特殊需要。在我的例子中,如原始问题中所述,我需要为我的目标web服务XML命名空间定义并使用别名,
xmlns=”http://tempuri.org“
,如上所述

要做到这一点,我必须

  • 获取对操作节点的引用,
    , 它将始终是
  • 删除将默认命名空间设置为目标的属性 名称空间
  • 设置节点的前缀(命名空间别名)
  • 执行此操作的修改后的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;
        }
    }
    

    这有用吗:?谢谢你的回复。这似乎是可行的。它要求手动修改所有消息约定。这个API中有很多这样的内容。我最终找到了一个更简单的解决方案。再次感谢。