C# WS-call中的null参数和省略参数之间的差异?

C# WS-call中的null参数和省略参数之间的差异?,c#,wcf,web-services,soap,axis2,C#,Wcf,Web Services,Soap,Axis2,假设我有一个WSDL,它定义了一个接受复杂类型的操作,这是非常常见的webmethod,比如: <xs:element name="createBill"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="customer" nillable="true" type="xs:string" /> <xs:ele

假设我有一个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>
为了透露更多的背景,我和一个Java家伙有一个问题。他的web服务是在Axis2中完成的,并且(出于我奇怪的原因)对待bill元素的省略与nil值不同。我的主张是,它们是一个,并且在两种情况下都应该表现相同(例如,创建动态billID)。他的声明是,这不一样,他只在节点缺失时生成动态ID,否则在节点为nilled时返回一个错误(“billId缺失”)

我对他的说法所遇到的实际问题是,.NET中的WCF和WS-stack都将它们视为一个整体,甚至没有规定省略可为零的参数,这使得我几乎不可能在不编写自己的WS-stack以及他实现的WS-Security的情况下实现客户机。目前,我只能调用指定null的服务:

serv.createBill("1332400", null);
serv.createBill("1332400"); // ERROR: no such method
我甚至不明白他是如何用Java实现服务器端的,这样一个web方法就有不同的调用模式,当省略节点时,Axis2将billID参数设置为什么?他非常不合作,我需要一些论据(如果有的话)向他提出,然后再向他的经理提出,因为他们在支持合同下


既然我们不能都是对的,那么有人知道WS标准在这里规定了什么吗?谁对标准有过错?我不是要开始wcf vs axis flame(请避免),我需要从SOAP/WSDL标准和规范作为两者的父级的角度来看待这个问题。

无法说明axis服务是否符合某些WS-standard关于可空值的规定,但您可以通过设置默认值来调整wcf客户端生成的代码。如果将其设置为false,则当可空类型的值为null时,WCF将不会创建相应的XML元素,这似乎是服务所要查找的内容。

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

还请注意,没有描述如何将WSDL和模式转换为特定于语言的构造的通用标准

也就是说,minOccurs=“0”和nillable=“true”结合在一起是有问题的,因为大多数语言只有一个概念,即null值,表示没有值。当使用minOccurs=“0”或nillable=“true”声明元素时,使用null值可以很好地工作,但没有自然的方法来处理同时使用这两种方法声明的元素。JAX-WS规范解决了这个问题,如以下问题所述:


与JAX-WS不同,其他一些特定于语言的Web服务绑定约定无法正确解决此问题,并且使用minOccurs=“0”和nillable=“true”通常会导致互操作性问题。因此,这应该被视为一种不好的做法,但不幸的是,Web服务规范中没有禁止这种做法。

不幸的是,这不起作用。它适用于
DataContract
,但操作的输入复杂类型被转换为
MessageContract
,并且
DataMember
属性对消息序列化没有影响。可能有一个
MessageContract
等价物吗?虽然这里的内容是“已退役”,但我相信它仍然有效。它展示了如何使用带有标记有
MessageContract
属性的WCF服务的
DataContract
标记类。我确实尝试了你的建议,甚至尝试了使用messages方法(使用请求/响应对象时不需要方法参数)。在这两种情况下,我都用
EmitDefaultValue
修饰billId,在这两种情况下,nil'ed bilID都在soap消息中。无论提到的MSDN文章是什么,都不再在WCF堆栈中了。因此,据我所知,他是对的,尽管这毫无意义,但仅仅从技术上来说,这种区别是可能的。微软在课堂上没有集中注意力,也没有(至少)为@sixto saez提供帮助,这是微软的过错。嗯,这不是我所希望的答案,但它确实有意义,不幸的是,这不是WCF与WS的第一个问题-*
serv.createBill("1332400", null);
serv.createBill("1332400"); // ERROR: no such method