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服务,因为它必须这样做.
我认为您应该定义一个单独的 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 属性的某种组合来装饰资产类型、属性和资产属性,以使其正常工作。
不用说,每当您需要重新生成代理代码时,您都必须重新应用上述更改(也许您可以为此创建一个批处理脚本作为构建操作)。