如何修复Visual Studio生成的用于处理锯齿状数组的Web引用代理?

Mic*_*out 5 .net xsd wsdl web-services xml-serialization

似乎wsdl.exe中存在一个已知错误,即Visual Studio用于生成Web服务代理的工具.使用某些XSD架构,该工具将生成无法从XML反序列化的类.

至于我担心这是不可接受的,但我不知道如何解决它.

我将详细描述我的案例,希望有人能够帮助我.

架构

<!-- return type from the service operation -->
<xs:complexType name="listAssetsQueryResults">
    <xs:sequence>
        <xs:element name="assets" type="tns:asset" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

<!-- a sequence of attributes -->
<xs:complexType name="asset">
    <xs:sequence>
        <xs:element name="attributes" type="tns:multiValuedAttribute" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="multiValuedAttribute">
    <!-- not relevant-->
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

来自Web服务的XML响应

根据此模式的典型响应如下所示:

<assets-query-result>
    <assets>
        <attributes>
            <name>Keywords</name>
            <values>Desert</values>
        </attributes>
        <attributes>
            <name>Filename</name>
            <values>Desert.jpg</values>
        </attributes>
    </assets>
    <assets>...</assets>
    <assets>...</assets>
</assets-query-result>
Run Code Online (Sandbox Code Playgroud)

使用代码中的类型

我原以为能够使用这样的CLR类型:

result.assets[0].attributes[0].name
Run Code Online (Sandbox Code Playgroud)

相反,生成的结果类型如下所示:

[SerializableAttribute()]
public partial class listAssetsQueryResults {
    private multiValuedAttribute[][] assetsField;

    [XmlArrayAttribute(Form=XmlSchemaForm.Unqualified, IsNullable=true)]
    [XmlArrayItemAttribute("attributes", typeof(multiValuedAttribute), Form=XmlSchemaForm.Unqualified)]
    public multiValuedAttribute[][] assets {
        get { return this.assetsField; }
        set { this.assetsField = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个甚至不允许生成序列化程序集!

无法将Portfolio.WebService.multiValuedAttribute类型转换为Portfolio.WebService.multiValuedAttribute []

解决它

1 - 更改属性和字段的类型

现在,我在网上找到的修复之一就是从生成的属性类型中删除一对括号:

// No longer a jagged array, but this doesn't deserialize all data
public multiValuedAttribute[] assets;
Run Code Online (Sandbox Code Playgroud)

这允许构建序列化程序集,并且它无异常地运行,除了它没有正确地序列化数据,它"跳过"资产列表并反序列化第一个assets元素的属性.所以它根本不是修复,因为有了这个修复,我无法使用数据.对于700多个资产,它给出result.assets的等于multiValuedAttribute[2](2个元素是第一个资产的名称和关键字属性).

2 - 指定XML元素的类型

我尝试的第二件事是给反序列化器提供不同的指令:

[XmlArrayItemAttribute("attributes", typeof(multiValuedAttribute[]), Form=XmlSchemaForm.Unqualified)]
public multiValuedAttribute[][] assets { ... }
Run Code Online (Sandbox Code Playgroud)

所以现在我告诉它序列中的每个元素都是类型multiValuedAttribute[].这是错误的,因为它仍在查看attributes类型的元素multiValuedAttribute(单个,而不是数组).它确实运行,但现在result.assets等于multiValuedAttribute[2][0],我仍然无法获取数据.

下一步是什么?

我不知道,这就是我写这个的原因.我无法接受.NET无法使用此Web服务,因为它必须这样做.

Vin*_*ayC 3

我认为您应该定义一个单独的 Asset 类,该类具有 multiValuedAttribute[] 类型的属性。所以它会像这样

public class Asset
{
   public multiValuedAttribute[] attributes {get; set;}
}

public partial class listAssetsQueryResults {
    private Asset[] assetsField;

    public Asset[] assets {
Run Code Online (Sandbox Code Playgroud)

然后,您需要使用 XmlElement/XmlArrayElement/XmlArrayItemElement 属性的某种组合来装饰资产类型、属性和资产属性,以使其正常工作。

不用说,每当您需要重新生成代理代码时,您都必须重新应用上述更改(也许您可以为此创建一个批处理脚本作为构建操作)。