WCF服务+ SvcUtil生成意外的对象结构

时间:2016-01-28 13:12:57

标签: c# wcf soap wsdl svcutil.exe

我正在尝试创建一个WCF应用程序,该应用程序将侦听来自供应商系统的请求。供应商为我提供了WSDL,因此我需要创建一个服务并将其“端点”暴露给他们。

我已经使用SvcUtil.exe来生成C#类,但它输出了相当奇怪的类型。

这是给我的WSDL的片段:

<?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 个答案:

答案 0 :(得分:1)

事实证明,类定义和定义在这里确实不是问题(它确实会引起另一个问题,但一旦你理解了什么,它就很容易解决)。这个问题植根于我在一次性开发阶段所做的事情。

我做的第一件事是使用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,Namespace等

最终,我能够使用WCF测试客户端成功调用应用程序中的端点。然而,当涉及与其通信的其他应用程序时,它根据原始问题失败了。我在WCF测试客户端中使用它所做的更改实际上使服务对原始WSDL架构无效!

<强> TL; DR;

不要使用WCF测试客户端构建您的WCF应用程序来测试它们。我不能强调这一点。它会强制您删除会导致应用程序在正常使用中中断的内容。即使在早期开发阶段,也要使用SoapUI等行业标准应用程序。

有用的链接