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

标签 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 正确输出。

最佳答案

TL;DR;

不要使用 WCF 测试客户端构建您的 WCF 应用程序来测试它们。我怎么强调都不为过。它会强制您删除会导致您的应用程序在正常使用中中断的内容。甚至从早期开发阶段就使用 SoapUI 等行业标准应用程序。


事实证明,类定义和定义并不是这里的真正问题(它确实会在稍后引起另一个问题,但一旦您了解发生了什么,这也很容易解决)。这个问题的根源在于我在一次性开发阶段所做的事情。

我做的第一件事是使用 svcutil.exe 使用供应商提供的 WSDL 生成服务器类。一旦我有足够的时间开始调试/测试,我自然会转向 WCF 测试客户端和 Visual Studio 的内置开发服务器。使用客户端时,它不断出现各种模糊的错误,例如不支持 https,契约(Contract)和绑定(bind)问题等。其中许多是配置不一致,因此通过一些谷歌搜索得到了修复,但其中的错误是:

WCF 测试客户端不支持该操作,因为它使用类型 SubmitIncident

当任何 SubmitIncident 的属性都是 object 类型时(即使嵌套在其他属性中),就会发生这种情况。基本上,我一次只是在处理一个错误,剔除一些直到最后它才起作用的部分。 我主要是在属性和类上添加和删除属性,例如DataMember、SoapAction、命名空间等

最终,我能够使用 WCF 测试客户端成功调用应用程序中的端点。但是,当涉及到与它通信的其他应用程序时,它按照最初的问题失败了。我为使其在 WCF 测试客户端中运行所做的更改实际上使该服务对原始 WSDL 模式无效!

有用的链接

关于c# - WCF 服务 + SvcUtil 生成意外的对象结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35062506/

相关文章:

C# WCF - 查找被调用的端点的名称

wcf - WCF独立进程是否会意外终止?

python - ServiceNow - 如何使用 SOAP 下载报告

c# - 从 Objectdatasource 上的 FetchCount() 访问时 Hiddenfield 为空

c# - 隐式定义的泛型类型,这可能吗?

ajax - Windows 服务通过 SSL (https) 托管 WCF 对象 - 自定义 JSON 错误处理不起作用

java - 带有 Retrofit2 订单问题的 SOAP

c# - 获取没有名称的窗口句柄

c# - 从 Intptr 读取一个字节

php - 如何在 PHP 中显式设置 NuSOAP 的参数类型