WCF 服务 + SvcUtil 生成意外的对象结构
Posted
技术标签:
【中文标题】WCF 服务 + SvcUtil 生成意外的对象结构【英文标题】:WCF service + SvcUtil generating unexpected object structure 【发布时间】:2016-05-05 21:19:48 【问题描述】:我正在尝试创建一个 WCF 应用程序来侦听来自供应商系统的请求。供应商为我提供了一个 WSDL,因此我需要创建一个服务并向他们公开它的端点。
我使用 SvcUtil.exe 生成 C# 类,但它输出的类型看起来很奇怪。
这是给我的WSDL的sn-p:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified">
<s:element name="Submit">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Incident">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="TransactionId" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="TransactionType" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="TransactionSubType" type="s:string" />
<s:element minOccurs="0" maxOccurs="unbounded" form="unqualified" name="ConfigurationItem">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="AssetTag" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Name" type="s:string" />
....
我运行的命令很简单
svcutil.exe file_name.wsdl
我希望这会创建一个这样的结构:
class Submit ...
class Incident ...
class ConfigurationItem ...
所以当它被序列化时,我会得到类似的东西:
<Submit>
<Incident>
<TransactionId>12345</TransactionId>
<TransactionType>12345</TransactionType>
<TransactionSubType>12345</TransactionSubType>
<ConfigurationItem>
<AssetTag>xyz</AssetTag>
<Name>name</Name>
</ConfigurationItem>
</Incident>
</Submit>
但是,SvcUtil.exe 的输出给了我以下信息:
class SubmitIncident ...
class SubmitIncidentConfigurationItem ...
它似乎将 Submit 和 Incident 对象合并为一个,并且它还在每个嵌套元素上添加了“SubmitIncident”。所以在序列化时我得到了这个:
<SubmitIncident>
<TransactionId>...</TransactionId>
<TransactionType>...</TransactionType>
<TransactionSubType>...</TransactionSubType>
<SubmitIncidentConfigurationItem>
<AssetTag>...</AssetTag>
<Name>...</Name>
</SubmitIncidentConfigurationItem>
</SubmitIncident>
这会导致供应商出现问题(我的服务与他们的 WSDL 不匹配,因此他们无法与我交谈)以及我在应用程序中进行的后续处理。谁能帮我理解为什么会发生这种情况,如何阻止它,并让 SvcUtil 正确输出。
【问题讨论】:
【参考方案1】:TL;DR;
不要使用 WCF 测试客户端来构建您的 WCF 应用程序来测试它们。这点我怎么强调都不为过。它迫使您删除会导致您的应用程序在正常使用中中断的东西。即使在早期开发阶段,也可以使用像 SoapUI 这样的行业标准应用程序。
事实证明,类定义和定义并不是这里真正的问题(它确实会在以后引起另一个问题,但一旦您了解发生了什么,这也很容易解决)。问题的根源在于我在一次性开发阶段所做的事情。
我做的第一件事是使用svcutil.exe
使用供应商提供的 WSDL 生成服务器类。一旦我有足够的时间开始调试/测试,我自然会前往 WCF 测试客户端和 Visual Studio 的内置开发服务器。在使用客户端时,它不断出现各种晦涩的错误,例如https 不支持,合同和绑定等问题。其中许多是配置不一致,因此通过一些谷歌搜索修复,但其中的错误是:
The operation is not supported in the WCF Test Client because it uses type SubmitIncident
当SubmitIncident
的任何属性为object
类型时,就会发生这种情况(即使嵌套在其他属性的下方)。基本上,我一次只处理一个错误,取出那些直到最终它才起作用的部分。 主要是我在属性和类上添加和删除属性,例如DataMember、SoapAction、命名空间等
最终,我能够使用 WCF 测试客户端成功调用应用程序中的端点。但是,当涉及与它通信的其他应用程序时,它按照原始问题失败了。我为使其在 WCF 测试客户端中工作而进行的更改实际上使该服务对原始 WSDL 架构无效!
有用的链接
http://blogs.msdn.com/dotnetinterop/archive/2008/09/24/wsdl-first-development-with-wcf.aspx http://wscfblue.codeplex.com/【讨论】:
那么有什么方法可以保留原始的 wsdl 层次结构,使用正确的类型命名并且没有前置类型名称?以上是关于WCF 服务 + SvcUtil 生成意外的对象结构的主要内容,如果未能解决你的问题,请参考以下文章
WCF:Svcutil 生成无效的客户端代理、Apache AXIS Web 服务、重载操作