在没有 "wsimport" 的情况下使用 XML SOAP Web 服务

Cosuming XML SOAP Webservice without "wsimport"

我的问题与下面post中的问题类似:。基本上,我的问题是使用 wsimport 生成客户端代码并没有真正失败,而是生成了一个警告“[WARNING] Port "reqReplyEndpoint" does not contain any usable operations”。这会导致不完整的代码生成,例如我在生成的 request/reqponse 类 中缺少参数。它是托管在 IIS 上的 WCF 服务,使用 WCF 消息路由服务。 IIS 将所有服务请求路由到端点。我无法控制这项服务,我只能接受它。知道如何在没有工作 wsimport 的情况下实现这一点,例如aksappy提到的方法?是否有任何框架、示例可用?以及提到的使用模式验证器在运行时检查 WSDL 然后基于它具有单独的解析机制的解决方案?

刚刚查看了您的包裹。

您的 WSDL 包含两项服务,一项名为 reqReplyEndpoint,另一项名为 BasicHttpBinding_TestTableService。我很确定,您想继续 BasicHttpBinding_TestTableService 因为另一个里面有空定义(没有定义操作等,参见 xppservice-wsdl0.xml)

因此: "[WARNING] Port "reqReplyEndpoint" does not contain any usable operations" 不是空 TestTableServiceGetListRequest 的原因。这是两个独立的 wsdl:services 之间没有直接关系。抛出此警告,因为名称为 "reqReplyEndpoint" 的绑定指向名为 "IRequestReplyRouter" 的端口类型,其中定义为空(只需将内容 xppservice-wsdl0.xml 与 xppservice-wsdl1.xml). 这样做的原因一定是在您的代码中的某个地方,我不是 C# WSDL 专家(但总体上在 WSDLs/Webservices 方面非常有经验)。

下一个: 您的 WSDL 包含三个具有名称的操作: 创建会员 删除会员 获取列表

getList 的 WSDL-result (SOAP env) 根据 soapUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://schemas.microsoft.com/dynamics/2010/01/datacontracts" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:ser="http://ax.bernina.com/01/services">
   <soapenv:Header>
      <dat:CallContext>
         <!--Optional:-->
         <dat:Company>?</dat:Company>
         <!--Optional:-->
         <dat:Language>?</dat:Language>
         <!--Optional:-->
         <dat:LogonAsUser>?</dat:LogonAsUser>
         <!--Optional:-->
         <dat:MessageId>?</dat:MessageId>
         <!--Optional:-->
         <dat:PropertyBag>
            <!--Zero or more repetitions:-->
            <arr:KeyValueOfstringstring>
               <arr:Key>?</arr:Key>
               <arr:Value>?</arr:Value>
            </arr:KeyValueOfstringstring>
         </dat:PropertyBag>
      </dat:CallContext>
   </soapenv:Header>
   <soapenv:Body>
      <ser:TestTableServiceGetListRequest/>
   </soapenv:Body>
</soapenv:Envelope>

你看,ser:TestTableServiceGetListRequest 是空的,因为底层基础 xsd (xppservice-xsd3.xml) 包含一个空定义:

   <xs:element name="TestTableServiceGetListRequest">
      <xs:complexType>
         <xs:sequence/>
      </xs:complexType>
   </xs:element>

如果您希望 TestTableServiceGetListRequest 中有更多参数,您应该检查相应的源代码(它负责 WSDL 结果 - 我不是在谈论 wsimport 结果)是否缺少某些内容(注释或类似内容)。

另外:我建议 contract-first 设计(首先创建 WSDL,然后从中生成代码)而不是 code-first 设计,因为如您所见,代码的结果可能是不像预期的那样,在代码中搜索根本原因可能很困难。

编辑 1 关于评论中的问题 1:

如果要将 CallContext 从 soap:header 移动到 soap:body,需要在 wsdl (xppservice-wsdl.xml) 中更改以下内容:

之前:

 <wsdl:operation name="getList">
         <soap:operation soapAction="http://ax.bernina.com/01/services/TestTableService/getList" style="document"/>
         <wsdl:input name="TestTableServiceGetListRequest">
            <soap:header message="i1:TestTableServiceGetListRequest_Headers" part="context" use="literal"/>
            <soap:body use="literal"/>
         </wsdl:input>
         <wsdl:output name="TestTableServiceGetListResponse">
            <soap:body use="literal"/>
         </wsdl:output>
         <wsdl:fault name="AifFaultFault">
            <soap:fault name="AifFaultFault" use="literal"/>
         </wsdl:fault>
      </wsdl:operation>

之后:

 <wsdl:operation name="getList">
         <soap:operation soapAction="http://ax.bernina.com/01/services/TestTableService/getList" style="document"/>
         <wsdl:input name="TestTableServiceGetListRequest">
            <soap:body message="i1:TestTableServiceGetListRequest_Headers" part="context" use="literal"/>
         </wsdl:input>
         <wsdl:output name="TestTableServiceGetListResponse">
            <soap:body use="literal"/>
         </wsdl:output>
         <wsdl:fault name="AifFaultFault">
            <soap:fault name="AifFaultFault" use="literal"/>
         </wsdl:fault>
      </wsdl:operation>