【问题标题】:.NET call webservices and returns nulls.NET 调用 web 服务并返回空值
【发布时间】:2012-01-08 21:41:27
【问题描述】:

我有一个 Web 服务,并将它添加到我的 .NET 项目中作为 Web 参考。其中一种 Web 方法返回一个嵌套数组 (NameValuePairDTOArray[NameValuePairDTO[])。我只能在 .NET 代码中获取空对象,但是当我通过 SoapUI 测试时它确实返回了数据。

我在这里粘贴了 wsdl 文件的一部分。

这是方法定义。

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://services.mymachine.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IneteractionService" targetNamespace="http://services.mymachine.com/">
    <operation name="getValue" parameterOrder="parameters">
        <input message="tns:MyServices_getValues"/>
        <output message="tns:MyServices_getValuesResponse"/>
        <fault message="tns:ServiceException" name="ServiceException"/>
    </operation>

    <xs:schema xmlns:ns1="http://ods.mymachine.com/v1_0_0" xmlns:tns="http://services.mymachine.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://services.mymachine.com/" version="1.0">
        <xs:import namespace="http://ods.mymachine.com/v1_0_0"/>
        <xs:element name="ServiceException" type="tns:ServiceException"/>
        <xs:element name="getValue" type="tns:getValue"/>
        <xs:element name="getValuesResponse" type="tns:getValuesResponse"/>
        <xs:complexType name="getValue">
            <xs:sequence>
            <xs:element minOccurs="0" name="firstName" type="xs:string"/>
            <xs:element minOccurs="0" name="lastName" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="getValuesResponse">
            <xs:sequence>
            <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="ns1:NameValuePairDTOArray"/>
            </xs:sequence>
        </xs:complexType>
    </xs:schema>
</definitions>

这是响应数据定义。

<xs:schema xmlns:ns1="http://common.mymanchine.com/v1_0_0" xmlns:tns="http://ods.mymachine.com/v1_0_0" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://ods.mymachine.com/v1_0_0" version="1.0">
    <xs:import namespace="http://common.mymanchine.com/v1_0_0"/>
    <xs:complexType final="#all" name="NameValuePairDTOArray">
        <xs:sequence>
        <xs:element maxOccurs="unbounded" minOccurs="0" name="item" nillable="true" type="tns:NameValuePairDTO"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="NameValuePairDTO">
        <xs:complexContent>
            <xs:extension base="ns1:DataTransferObject">
                <xs:sequence/>
                <xs:attribute name="name" type="xs:string"/>
                <xs:attribute name="value" type="xs:string"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema

.NET 生成的代理类如下:

[WebServiceBinding(Name = "InteractionServicesBinding", Namespace = "http://services.mymachine.com/")]
[XmlInclude(typeof(DataTransferObject))]
[DebuggerStepThrough]
[GeneratedCode("System.Web.Services", "4.0.30319.1")]
[DesignerCategory("code")]
public class InteractionServicesServiceWse : WebServicesClientProtocol
{
    public InteractionServicesServiceWse();

    [SoapDocumentMethod("", RequestNamespace = "http://services.mymachine.com/", 
     ResponseNamespace = "http://services.services.mymachine.com/", Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
    public NameValuePairDTOArray[] getValue(string firstName, string lastName);
}

[Serializable]
[XmlType(Namespace = "http://ods.mymachine.com/v1_0_0")]
[GeneratedCode("System.Xml", "4.0.30319.233")]
[DebuggerStepThrough]
[DesignerCategory("code")]
public class NameValuePairDTOArray
{
    public NameValuePairDTOArray();

    [XmlElement("item", IsNullable = true)]
    public NameValuePairDTO[] item { get; set; }
}

[Serializable]
[DesignerCategory("code")]
[XmlType(Namespace = "http://ods.mymachine.com/v1_0_0")]
[GeneratedCode("System.Xml", "4.0.30319.233")]
[DebuggerStepThrough]
public class NameValuePairDTO : DataTransferObject
{
    public NameValuePairDTO();

    [XmlAttribute]
    public string name { get; set; }
    [XmlAttribute]
    public string value { get; set; }
}

现在如果我调用 getValue("John", "Peter"),它将在 .NET 中返回如下。

但是soapUI会返回类似的东西:

<env:Body>
  <ns2:getValueResponse xmlns:ns2="http://services.mymachine.com/">
     <return>
        <item value="123" name="BONUS_ID"/>
        <item value="456" name="POPUP_OBJECT_ID"/>
     </return>
     <return>
        <item value="123" name="BONUS_ID"/>
        <item value="567" name="POPUP_OBJECT_ID"/>
     </return>
  </ns2:getValueResponse>
</env:Body>

.NET 似乎无法检测到 NameValuePairDTO/item 是一个数组。

怎么了?

【问题讨论】:

  • 自添加服务引用后,您是否对服务进行过任何更改?

标签: .net xml web-services soap


【解决方案1】:

嗯,问题原来是服务器端出了点问题。

架构定义了 NameValuePairDTOArray 和 NameValuePairDTO 是 quailifed。

但是看看响应xml,

<env:Body>
  <ns2:getValueResponse xmlns:ns2="http://services.mymachine.com/">
     <return>
        <item value="123" name="BONUS_ID"/>
        <item value="456" name="POPUP_OBJECT_ID"/>
     </return>
     <return>
        <item value="123" name="BONUS_ID"/>
        <item value="567" name="POPUP_OBJECT_ID"/>
     </return>
  </ns2:getValueResponse>

return(NameValuePairDTOArray) 和 item(NameValuePairDTO) 不合格。并且生成的代理类假定它们是合格的,因为定义了架构,但这导致解析xml失败。

快速解决方法是手动将 unqualifed 属性添加到 NameValuePairDTOArray 类中的 NameValuePairDTO 属性中。将来,服务端应该会解决此问题。

【讨论】:

    【解决方案2】:

    您在生成的代码中的 NameValuePairDTOArray 出现在命名空间“http://ods.mymachine.com/v1_0_0”中,但该命名空间不在 xml 输出中(因此 .net 不知道标签“return”是指到 NameValuePairDTOArray)。

    也许您从服务器的代码中删除了 XmlTypeAttribute。

    所以您应该:在客户端刷新您的 Web 引用或在服务器端添加回 XmlTypeAttribute。

    【讨论】:

    • 我也注意到了这一点并更改了 wsdl 文件,但它不起作用。
    • 问题不是 wsdl 文件,而是您的 Web 服务返回的 xml:您的服务器不遵守它创建的合同(wsdl 文件)
    猜你喜欢
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 2013-04-08
    • 2011-12-22
    • 2011-10-02
    • 1970-01-01
    相关资源
    最近更新 更多