【问题标题】:web service request call SOAP request missing empty parametersWeb 服务请求调用 SOAP 请求缺少空参数
【发布时间】:2011-06-24 11:49:10
【问题描述】:

我是 Web 服务和 C# 的新手,所以如果我的问题太简单,请原谅我。我四处搜索,但找不到答案——至少一个基于我的关键字的答案。

我正在尝试通过 C# (Visual Web Developer 2010 Express) 调用 Web 服务,但我收到一个错误作为响应。当我通过soapUI 调用相同的Web 服务时,我没有收到错误消息。当我将来自 C# 的 SOAP 请求与来自 soapUI 的 SOAP 请求进行比较时,C# SOAP 请求缺少一个故意为空的参数<aclObjectId>。当我从soapUI请求中取出空参数时,我得到了同样的错误。对我来说,答案是让 C# 发送参数,即使它是空的。我通过将其设置为 null 或 "" 进行了尝试,但无济于事。有没有办法强制我的 C# Web 服务客户端发送一个空参数或者发送所有参数,即使它们没有值?

WSDL

<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3-b02-. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3-b02-. --><definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://search.services.redacted/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://search.services.redacted/" name="EDRSearchServiceSOAPImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://search.services.redacted/" schemaLocation="http://wwwdev.redacted:80/EDRSearch?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="processSearch">
<part name="parameters" element="tns:processSearch"></part>
</message>
<message name="processSearchResponse">
<part name="parameters" element="tns:processSearchResponse"></part>
</message>
<message name="getAttributes">
<part name="parameters" element="tns:getAttributes"></part>
</message>
<message name="getAttributesResponse">
<part name="parameters" element="tns:getAttributesResponse"></part>
</message>
<message name="getACLUsers">
<part name="parameters" element="tns:getACLUsers"></part>
</message>
<message name="getACLUsersResponse">
<part name="parameters" element="tns:getACLUsersResponse"></part>
</message>
<portType name="EDRSearchServiceSOAPImpl">
<operation name="processSearch">
<input message="tns:processSearch"></input>
<output message="tns:processSearchResponse"></output>
</operation>
<operation name="getAttributes">
<input message="tns:getAttributes"></input>
<output message="tns:getAttributesResponse"></output>
</operation>
<operation name="getACLUsers">
<input message="tns:getACLUsers"></input>
<output message="tns:getACLUsersResponse"></output>
</operation>
</portType>
<binding name="EDRSearchServiceSOAPImplPortBinding" type="tns:EDRSearchServiceSOAPImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
<operation name="processSearch">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
<operation name="getAttributes">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
<operation name="getACLUsers">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
</binding>
<service name="EDRSearchServiceSOAPImplService">
<port name="EDRSearchServiceSOAPImplPort" binding="tns:EDRSearchServiceSOAPImplPortBinding">
<soap:address location="http://wwwdev.redacted:80/EDRSearch"></soap:address>
</port>
</service>
</definitions>

C# SOAP(不起作用)

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getACLUsers xmlns="http://search.services.redacted/">
      <ACLUsersRequest xmlns="">
        <docbase>edmsdev</docbase>
        <aclName>my_acl</aclName>
      </ACLUsersRequest>
      <userCredentials xmlns="">
        <userName>spoonyfork</userName>
        <password>my_password</password>
        <docbase>edmsdev</docbase>
      </userCredentials>
    </getACLUsers>
  </s:Body>
</s:Envelope>

soapUI SOAP(有效)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sear="http://search.services.redacted/">
   <soapenv:Header/>
   <soapenv:Body>
      <sear:getACLUsers>
         <!--Optional:-->
         <ACLUsersRequest>
            <docbase>edmsdev</docbase>
            <aclName>my_acl</aclName>
            <aclObjectId></aclObjectId>
         </ACLUsersRequest>
         <!--Optional:-->
         <userCredentials>
            <userName>spoonyfork</userName>
            <!--Optional:-->
            <password>my_password</password>
            <!--Optional:-->
            <wsl4cookie></wsl4cookie>
            <!--Optional:-->
            <endUserForProxyId></endUserForProxyId>
            <!--Optional:-->
            <ip></ip>
            <!--Optional:-->
            <docbase>edmsdev</docbase>
         </userCredentials>
      </sear:getACLUsers>
   </soapenv:Body>
</soapenv:Envelope>

EDRSearch XSD

<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3-b02-. --><xs:schema xmlns:tns="http://search.services.redacted/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://search.services.redacted/">

<xs:element name="getACLUsers" type="tns:getACLUsers"></xs:element>

<xs:element name="getACLUsersResponse" type="tns:getACLUsersResponse"></xs:element>

<xs:element name="getAttributes" type="tns:getAttributes"></xs:element>

<xs:element name="getAttributesResponse" type="tns:getAttributesResponse"></xs:element>

<xs:element name="processSearch" type="tns:processSearch"></xs:element>

<xs:element name="processSearchResponse" type="tns:processSearchResponse"></xs:element>

<xs:complexType name="getACLUsers">
<xs:sequence>
<xs:element name="ACLUsersRequest" type="tns:ACLUsersRequest" minOccurs="0"></xs:element>
<xs:element name="userCredentials" type="tns:UserCredentials" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="ACLUsersRequest">
<xs:sequence>
<xs:element name="docbase" type="xs:string"></xs:element>
<xs:element name="aclName" type="xs:string"></xs:element>
<xs:element name="aclObjectId" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="UserCredentials">
<xs:sequence>
<xs:element name="userName" type="xs:string"></xs:element>
<xs:element name="password" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="wsl4cookie" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="endUserForProxyId" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="ip" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="docbase" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="getACLUsersResponse">
<xs:sequence>
<xs:element name="return" type="tns:ACLUsersResponse" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="ACLUsersResponse">
<xs:sequence>
<xs:element name="user" type="xs:string" maxOccurs="unbounded"></xs:element>
<xs:element name="largeGroups" type="xs:string" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="processSearch">
<xs:sequence>
<xs:element name="searchRequest" type="tns:searchRequest" minOccurs="0"></xs:element>
<xs:element name="userCredentials" type="tns:UserCredentials" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="searchRequest">
<xs:sequence>
<xs:element name="version" type="xs:string"></xs:element>
<xs:element name="docbase" type="xs:string"></xs:element>
<xs:element name="searchCriteria" type="tns:logicalOp" maxOccurs="unbounded"></xs:element>
<xs:element name="maxNumberOfDocuments" type="xs:string"></xs:element>
<xs:element name="folderPaths" type="xs:string" maxOccurs="unbounded"></xs:element>
<xs:element name="metaDataList" type="xs:string" maxOccurs="unbounded"></xs:element>
<xs:element name="objectType" type="xs:string"></xs:element>
<xs:element name="documentLaunchSettings" type="tns:documentLaunchSettings"></xs:element>
<xs:element name="documentACLSettings" type="tns:documentACLSettings"></xs:element>
<xs:element name="oracleHint" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="logicalOp">
<xs:sequence>
<xs:element name="type" type="xs:string"></xs:element>
<xs:element name="name" type="xs:string"></xs:element>
<xs:element name="value" type="xs:string"></xs:element>
<xs:element name="logical" type="xs:string"></xs:element>
<xs:element name="relational" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="documentLaunchSettings">
<xs:sequence>
<xs:element name="launcher" type="xs:string"></xs:element>
<xs:element name="useChronicleId" type="xs:boolean"></xs:element>
<xs:element name="showLink" type="xs:boolean"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="documentACLSettings">
<xs:sequence>
<xs:element name="returnACL" type="xs:boolean"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="processSearchResponse">
<xs:sequence>
<xs:element name="return" type="tns:searchResponse" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="searchResponse">
<xs:sequence>
<xs:element name="docbase" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="documents" type="tns:document" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element>
<xs:element name="numberOfDocuments" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="document">
<xs:sequence>
<xs:element name="objectId" type="xs:string"></xs:element>
<xs:element name="linkLocation" type="xs:string"></xs:element>
<xs:element name="metaDataList" type="tns:metaDataItem" maxOccurs="unbounded"></xs:element>
<xs:element name="aclInfo" type="tns:ACLInfo" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="metaDataItem">
<xs:sequence>
<xs:element name="name" type="xs:string"></xs:element>
<xs:element name="value" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="ACLInfo">
<xs:sequence>
<xs:element name="ACLName" type="xs:string"></xs:element>
<xs:element name="ACLObjectId" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="getAttributes">
<xs:sequence>
<xs:element name="attributesRequest" type="tns:objectType" minOccurs="0"></xs:element>
<xs:element name="userCredentials" type="tns:UserCredentials" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="objectType">
<xs:sequence>
<xs:element name="docbase" type="xs:string"></xs:element>
<xs:element name="objectType" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="getAttributesResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>

C#代码

ServiceReference1.UserCredentials uc = new ServiceReference1.UserCredentials();
uc.userName = "spoonyfork";
uc.password = "my_password";
uc.docbase = "edmsdev";

ServiceReference1.ACLUsersRequest aurt = new ServiceReference1.ACLUsersRequest();
aurt.aclName = "my_acl";
aurt.docbase = "edmsdev";

ServiceReference1.EDRSearchServiceSOAPImplClient client = new ServiceReference1.EDRSearchServiceSOAPImplClient();
ServiceReference1.ACLUsersResponse aure = new ServiceReference1.ACLUsersResponse();
aure = client.getACLUsers(aurt, uc);

【问题讨论】:

  • 是空值还是类型?出于合同目的需要知道类型...
  • 值为空。 edmsdevmy_acl
  • @spoonyfork 很难回答没有位于@wwwdev.redacted:80/EDRSearch?xsd=1 的导入类型的 WSDL 定义,因此您可以更好地为我们提供从服务参考和您的方式生成的 C# 类正在使用它们(很明显,在 SoapUI 中,'aclObjectId' 不是可选参数)。
  • @ilya-dvorovoy 我在上面添加了 xsd 和我的 C# 代码。我没有为 aclObjectId 设置值,因为该服务的文档说它是 aclObjectId 或 aclName 而不是两者。如果我同时设置两者,我会收到回复说不要同时设置两者。我认为我需要做的是让 C# 发送一个空的 aclObjectId 但我不知道该怎么做。 aurt.aclObjectId = ""; 不会像我希望的那样神奇地在 SOAP 中放置一个空的 &lt;aclObjectId&gt;
  • @spoonyfork 你可以查看我的答案,但是当你不提供任何&lt;aclObjectId&gt; 时,你会收到什么样的错误消息?

标签: c# .net web-services soap


【解决方案1】:

首先,您可以尝试声明aclObjectId 属性以进行序列化,即使它是null。为此,您需要找到 class ACLUsersRequest 的定义并添加

[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]

对于该属性。 这会将其作为&lt;aclObjectId xsi:nil="true" /&gt; 包含到SOAP 请求中

其次,您可以简单地将该属性声明为string.Empty

EDRSearchServiceSOAPImplClient client = new EDRSearchServiceSOAPImplClient();
var test = client.getACLUsers(
    new ACLUsersRequest() {
        aclName = "my_acl",
        docbase = "qwe",
        aclObjectId=string.Empty },//this should do the trick
    new UserCredentials() {
        userName = "lala",
        password = "123",
        docbase = "qwe" });

这会将其作为&lt;aclObjectId /&gt; 包含到SOAP 请求中,这等于&lt;aclObjectId&gt;&lt;/aclObjectId&gt;

如果这两种方法都不起作用,那么您正在与非常糟糕的网络服务提供商打交道,并且需要实现自己编写的客户端,该客户端将按照提供商的强制格式设置消息。

【讨论】:

    【解决方案2】:

    目前为止我唯一能找到的东西:

    http://www.w3.org/TR/2007/REC-soap12-part2-20070427/

    4.2.1
    Applications MAY process invocations with missing parameters but also MAY fail to process the invocation and return a fault.
    

    您是否手动生成了网络参考?你能提供适当的 WSDL 吗? + 我可以更新这个答案


    <operation name="getACLUsers">
        <soap:operation soapAction=""></soap:operation>
        <input>
            <soap:body use="literal"></soap:body>
        </input>
        <output>
            <soap:body use="literal"></soap:body>
        </output>
    </operation>
    

    在我看来,SOAP 级别没有多个参数,只有一个说 XML 或字符串参数。 getAclUsers 是否有多个参数?

    我承认我的 SOAP 知识有限,但是 WSDL 中没有列出任何参数...也许您正在序列化为 XML,而您应该查看 XML 序列化选项?

    【讨论】:

    • Web 引用是指 Visual Web Developer 2010 定义的服务引用吗?如果是这样,那么不,我使用了添加服务引用向导并提供了 WSDL URL。我没有手动生成任何东西。我已将 WSDL 添加到上面的原始问题中。相关部分是 getACLUsers。
    • @kieren-johnstone 我包含了上面的 XSD 代码,它确实拼出了参数。我的问题仍然是我不知道如何从 C# 发送一个空的&lt;aclObjectId&gt;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多