【问题标题】:WCF - Customized client request/response XMLWCF - 自定义客户端请求/响应 XML
【发布时间】:2011-02-25 17:57:58
【问题描述】:

我正在尝试使用供应商提供的带有 WCF 客户端的 AXIS Web 服务。该服务期望将请求/响应元素 <TXLife> 作为 SOAP 主体的根元素(没有操作元素包装它)。我正在使用 XmlSerializer,因为我的数据合同有一些自定义 ACORD 架构特性。例如,服务器希望看到以下内容(...是的,“服务”是操作的名称...):

...<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><TXLife><TXLifeRequest xmlns="">...    

我的客户正在生成 XML,操作序列化为包装元素,如下所示:

...<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><service xmlns="urn:example.servicecontract"><TXLife><TXLifeRequest xmlns="">...

使用“extra”标签指示请求中的操作,服务无法处理请求和错误。如果我删除 &lt;service&gt; 标记,Web 服务会愉快地处理请求。

不幸的是,该服务还以未包装的&lt;TXLife&gt; 标记作为根元素向下发送响应:

...<soapenv:Body><TXLife xmlns=""><TXLifeResponse>...

我的反序列化程序没有正确处理响应,我得到了一个 null 对象。我假设是因为我的客户期望一个服务操作响应包装器标签而没有得到一个。在反序列化级别,我没有从调试器那里得到太多帮助。

我正在考虑实现 IClientMessageFormatter 甚至 IClientMessageInspector 来修改请求/响应(例如,从请求消息中删除操作标记并在响应消息中添加响应标记)。我知道 Formatter 是作为 OperationalBehavior 注入的,但我不确定 MessageInspector 适合堆栈的位置。也许我会以错误的方式解决这个问题...... 任何见解或建议将不胜感激。原谅我,这是我第一次尝试 WCF 服务,我正在慢慢摸索。不幸的是,关于这项服务的一切似乎都是“定制的”。

我的服务合同:

[XmlSerializerFormat]
[ServiceContract(Namespace="urn:example.servicecontract")]
public interface IPayoutServiceContract
{
    [OperationContract]
    TXLife service([MessageParameter(Name = "TXLife")]TXLife request);
}

服务 WSDL 的一部分:

<wsdl:types><schema targetNamespace="urn:Tx103Service" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><import id="tx" namespace="http://ACORD.org/Standards/Life/2" schemaLocation="../acord/TXLife2.8.92.xsd" /></schema></wsdl:types><wsdl:message name="serviceRequest"><wsdl:part element="tx:TXLife" name="acordRequest" /></wsdl:message><wsdl:message name="serviceResponse"><wsdl:part element="tx:TXLife" name="acordResponse" /></wsdl:message><wsdl:portType name="LifeWebService"><wsdl:operation name="service"><wsdl:input message="impl:serviceRequest" name="serviceRequest" /><wsdl:output message="impl:serviceResponse" name="serviceResponse" /></wsdl:operation></wsdl:portType>

更新:

我首先尝试在代理类上使用MessageContract(isWrapped=false) 装饰器(接口不允许这样做)。那什么也没做。我还尝试了BodyStyle = WebMessageBodyStyle.Bare 的口味,也没有。我认为这是由于我正在使用的 XMLSerializer。在我看来,解决这个问题没有简单的方法来“装饰”我的方式。

顺便说一句:我的服务合同、数据合同和代理客户端都根据这个建议在不同的项目中,这对我来说听起来很可靠: blog post by Miguel Castro

更新2:

我创建了用 MessageContract/MessageBodyMember 标签装饰的请求/响应包装类。现在 XML 已按预期生成。仍然在响应中获取 null 对象...

更新3:

我的响应中的“null”对象实际上存在于 XML 响应中,但没有被反序列化,因为序列化程序正在寻找它们作为合格的对象。我将它们更改为不合格,之后我的对象就正常显示了。

【问题讨论】:

    标签: .net xml wcf


    【解决方案1】:

    您是否尝试过使用带有 IsWrapped=false 的 MessageContract 而不是使用 [MessageParameter]?

    【讨论】:

    • 我很困惑...您在界面上尝试过 MessageContract 吗?这不是如何使用的......您这样做的方式是创建一个类来表示消息,将其标记为 [MessageContract],然后您将在其中放置一个 TXLife 类型的属性,并用 [MessageBodyMember] 标记。然后你会使用这个新类作为操作参数(没有 [MessageParameter])
    • 我没有正确实现 MessageContracts。我相信我已经克服了困难,但我的服务现在已经关闭,更多的测试将不得不等待。更多来... ;)