【问题标题】:Difference between nulled and omitted parameter in WS call?WS调用中空参数和省略参数的区别?
【发布时间】:2012-09-06 17:35:35
【问题描述】:

假设我有一个 WSDL,它定义了一个接受复杂类型的操作,非常常见的 webmethod 类似这样的东西:

  <xs:element name="createBill">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" name="customer" nillable="true" type="xs:string" />
        <xs:element minOccurs="0" name="billId"   nillable="true" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <wsdl:message name="createBillRequest">
    <wsdl:part name="parameters" element="ns:createBill" />
  </wsdl:message>

  <wsdl:operation name="creatBill">
    <wsdl:input wsaw:Action="urn:createBill" message="axis2:createBillRequest" />
    ...
  </wsdl:operation>

两种不同调用的 WebServices 标准实现规则是什么,一个指定 billId 为xsi:nil,另一个完全省略节点?

<creatBill ...>
   <customer>1332400</customer>
   <billId xsi:nil="true"/>
</createBill>

vs

<creatBill ...>
   <customer>1332400</customer>
</createBill>

为了透露更多背景信息,我遇到了一位 Java 人员的问题。他的 Web 服务是在 Axis2 中完成的,并且(出于对我来说奇怪的原因)处理 bill 元素的省略与 nil 值不同。我的主张是它们是相同的,并且在两种情况下它的行为都应该相同(例如,创建一个动态的 billID)。他的说法是它不一样,他只在节点丢失时生成动态 ID,否则在节点被取消时返回错误(“billId 丢失”)。

我对他的说法的实际问题是 .NET 中的 WCF 和 WS 堆栈都将它们视为一回事,甚至没有规定省略可空参数,这使我几乎不可能实现客户端无需编写我自己的 WS-stack 以及他实现的 WS-Security。就目前而言,我只能调用指定 null 的服务:

serv.createBill("1332400", null);
serv.createBill("1332400"); // ERROR: no such method

我什至不明白他是如何在 Java 中实现服务器端的,因此一个 Web 方法具有不同的调用模式,当省略节点时,Axis2 设置的 billID 参数是什么?他非常不合作,我需要一些论据(如果有的话)向他提出,然后再向他的经理提出,因为他们签订了支持合同。

既然我们不能都对,有谁知道这里的 WS 标准规定了什么?谁对标准有过错?我不是开始讨论 wcf 与轴火焰(请不要),我需要从 SOAP/WSDL 标准和规范的角度来看待这个问题,作为两者的父级。

【问题讨论】:

    标签: c# wcf web-services soap axis2


    【解决方案1】:

    您的 Web 服务使用文档/文字样式。在这种情况下,Web 服务规范只要求消息内容(更具体地说是 SOAP 主体的单个子项)由 XML Schema 元素声明来描述,并且当然要符合该声明。现在,XML Schema 确实允许同时使用 minOccurs="0" 和 nillable="true",但是规范并没有将元素的缺失与 xsi:nil="true 的元素的缺失附加任何特定含义";特别是它没有声明这两种情况是等价的。由模式的设计者来定义这两种情况的含义。

    另请注意,没有通用标准来描述如何将 WSDL 和架构转换为特定于语言的结构。

    话虽如此,将 minOccurs="0" 和 nillable="true" 放在一起是有问题的,因为大多数语言只有一个概念,即空值,来表示值的缺失。如果使用 minOccurs="0" 或 nillable="true" 声明元素,则使用 null 值效果很好,但没有自然的方法来处理同时声明的元素。 JAX-WS 规范解决了这个问题,如以下问题所述:

    Jaxb generated class used JAXBElement instead of specified type

    与 JAX-WS 相比,其他一些特定于语言的 Web 服务绑定约定不能正确解决此问题,并且将 minOccurs="0" 与 nillable="true" 一起使用通常会导致互操作性问题。因此,这应该被视为一种不好的做法,但遗憾的是,Web 服务规范中没有任何内容禁止这样做。

    【讨论】:

    • 所以,据我了解,他是对的,虽然这完全没有意义,但仅凭技术优势就可以区分。微软在课堂上没有专心,并且没有(至少)提供@sixto-saez 提供的救济,这是错误的。嗯,不是我希望的答案,但它确实有道理,遗憾的是不是 WCF 与 WS-* 的第一个问题
    【解决方案2】:

    不能说 Axis 服务是否符合某些可空值的 WS 标准,但您可以通过设置 EmitDefaultValue setting of the DataMember attribute 来调整 WCF 客户端生成的代码。如果将其设置为 false,则当可空类型的值为 null 时,WCF 将不会创建相应的 XML 元素,这似乎是服务正在寻找的。​​p>

    【讨论】:

    • 不幸的是,这不起作用。它适用于DataContract,但操作的输入复杂类型被转换为MessageContractDataMember 属性对消息序列化没有影响。是否有 MessageContract 等价物?
    • 虽然这个MSDN article里面的内容已经“退休”了,但是我相信还是有效的。它展示了如何使用带有 DataContract 标记的类和带有 MessageContract 属性标记的 WCF 服务。
    • 我实际上确实尝试了您的建议,我什至尝试使用消息方法(其中使用请求/响应对象而不是方法参数)。在这两种情况下,我都用EmitDefaultValue 装饰了 billId,在这两种情况下,nil'ed bilID 都在肥皂信息中。 MSDN 文章中提到的任何内容都不再存在于 WCF 堆栈中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2015-10-07
    • 1970-01-01
    • 2015-02-11
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多