【问题标题】:SOAP requests in .NET.NET 中的 SOAP 请求
【发布时间】:2012-08-03 12:50:15
【问题描述】:

我们正在尝试使用 SOAP 请求与使用 Visual Studio C# 的预订 API 进行交互。

我们已经毫无问题地与另一个 API 的 Web 服务交互,但事实证明这个 API 存在问题。

我们已将其添加为服务参考,Visual Studio 已为其生成所有类和 web.config 条目,因此一切正常。

但是,当我们尝试向客户端 SOAP 服务发出简单请求时,我们会收到以下错误:

名称空间='com.hrs.soap.hrs' 不支持 rpc\literal SOAP。包装器元素必须是不合格的。

代码是:

PingRequest pingrequest = new PingRequest();    
SoapServiceClient service = new SoapServiceClient();
service.ping(pingrequest);

这是在 Web.config 文件中添加的内容:

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="HRSSoapServiceBinding" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="..."
          binding="basicHttpBinding" bindingConfiguration="HRSSoapServiceBinding"
          contract="HRSService.HRSSoapService" name="HRSSoapServicePort" />
    </client>
  </system.serviceModel>

根据文档,请求应如下所示:

<complexType name="PingRequest">
    <complexContent>
        <extension base="tns:Request">
            <sequence>
                <element name="echoData" type="xsd:string"/>
            </sequence>
        </extension>
    </complexContent>
</complexType>

下面的完整堆栈跟踪:

[InvalidOperationException: Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP. The wrapper element has to be unqualified.]
   System.Xml.Serialization.XmlReflectionImporter.CheckTopLevelAttributes(XmlAttributes a, String accessorName) +842469
   System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +4072651
   System.Xml.Serialization.XmlReflectionImporter.ImportMemberMapping(XmlReflectionMember xmlReflectionMember, String ns, XmlReflectionMember[] xmlReflectionMembers, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +699
   System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +298

[InvalidOperationException: There was an error reflecting 'HRSException'.]
  System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +1051
   System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(String elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, XmlMappingAccess access) +137
   System.ServiceModel.Description.XmlSerializerImporter.ImportMembersMapping(XmlName elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean isEncoded, String mappingKey) +237
   System.ServiceModel.Description.OperationReflector.ImportMembersMapping(String elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, String mappingKey) +134
   System.ServiceModel.Description.OperationReflector.ImportFaultElement(FaultDescription fault, XmlQualifiedName& elementName) +458
   System.ServiceModel.Description.OperationReflector.GenerateXmlSerializerFaultContractInfos() +153
   System.ServiceModel.Description.OperationReflector.EnsureMessageInfos() +929
   System.ServiceModel.Description.Reflector.EnsureMessageInfos() +98
   System.ServiceModel.Description.XmlSerializerOperationBehavior.CreateFormatter() +32
   System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy) +42
   System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) +94
   System.ServiceModel.Description.DispatcherBuilder.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) +247
   System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters) +342
   System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose) +85
   System.ServiceModel.ChannelFactory.CreateFactory() +43
   System.ServiceModel.ChannelFactory.OnOpening() +23
   System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +274
   System.ServiceModel.ChannelFactory.EnsureOpened() +107
   System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via) +134
   System.ServiceModel.ChannelFactory`1.CreateChannel() +29
   System.ServiceModel.ClientBase`1.CreateChannel() +91
   System.ServiceModel.ClientBase`1.CreateChannelInternal() +26
   System.ServiceModel.ClientBase`1.get_Channel() +261
   BLL.HRSService.HRSSoapServiceClient.ping(HRSPingRequest pingRequest) in C:\Code\-------\BLL\Service References\HRSService\Reference.cs:15850
   -------.Test.Ping() in C:\Code\-------\Test.aspx.cs:48
   -------.Test.Page_Load(Object sender, EventArgs e) in C:\Code\-------\Test.aspx.cs:24
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +91
   System.Web.UI.Control.LoadRecursive() +74
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

我们安装了 Fiddler,我们可以看到没有通过 XML 请求,大概是因为它在发送任何内容之前抛出异常。

我们需要对设置进行哪些更改才能使其正常工作?

更新

WSDL:可用[此处][1]

更新

按照 davidfmatheson 的出色建议,我在本地复制了 WSDL 并按照建议进行了修改。尽管可能在不同的地方,但我仍然遇到相同的错误:

[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
        BLL.HRSService.pingResponse BLL.HRSService.HRSSoapService.ping(BLL.HRSService.pingRequest request) {
            return base.Channel.ping(request);
        }

        public BLL.HRSService.HRSPingResponse ping(BLL.HRSService.HRSPingRequestWrapper ping1) {
            BLL.HRSService.pingRequest inValue = new BLL.HRSService.pingRequest();
            inValue.ping = ping1;
            BLL.HRSService.pingResponse retVal = ((BLL.HRSService.HRSSoapService)(this)).ping(inValue);
            return retVal.pingResponse1;
        }

失败的行是 return base.Channel.ping(request); 错误 Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP .包装器元素必须是不合格的。

我还尝试显式设置 SOAPBinding:

Exception Details: System.InvalidOperationException: Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP. The wrapper element has to be unqualified.

Source Error: 

Line 15917:        [System.Web.Services.Protocols.SoapDocumentMethod(Use = System.Web.Services.Description.SoapBindingUse.Literal)]
Line 15918:        BLL.HRSService.pingResponse BLL.HRSService.HRSSoapService.ping(BLL.HRSService.pingRequest request) {
Line 15919:            return base.Channel.ping(request);
Line 15920:        }
Line 15921:

好的,现在我已经修改了 SOAP 绑定样式以记录在我的本地 WSDL 中并重新创建了类,但我遇到了另一个错误:

Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelTaxDetail[]' to 'BLL.HRSService.HRSHotelTaxDetail'
error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelAmenityCriterion[]' to 'BLL.HRSService.HRSHotelAmenityCriterion'
error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelTaxDetail' to 'BLL.HRSService.HRSHotelTaxDetail[]'
error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelAmenityCriterion' to 'BLL.HRSService.HRSHotelAmenityCriterion[]'

堆栈跟踪:

[InvalidOperationException: Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelTaxDetail[]' to 'BLL.HRSService.HRSHotelTaxDetail'
error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelAmenityCriterion[]' to 'BLL.HRSService.HRSHotelAmenityCriterion'
error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelTaxDetail' to 'BLL.HRSService.HRSHotelTaxDetail[]'
error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelAmenityCriterion' to 'BLL.HRSService.HRSHotelAmenityCriterion[]'
]
   System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) +1024
   System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies) +1997
   System.Xml.Serialization.XmlSerializer.GetSerializersFromCache(XmlMapping[] mappings, Type type) +772
   System.Xml.Serialization.XmlSerializer.FromMappings(XmlMapping[] mappings, Type type) +4066268
   System.ServiceModel.Description.SerializerGenerationContext.GenerateSerializers() +185
   System.ServiceModel.Description.SerializerGenerationContext.GetSerializer(Int32 handle) +102
   System.ServiceModel.Description.MessageInfo.get_BodySerializer() +17
   System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest) +112

[CommunicationException: There was an error in serializing body of message pingRequest: 'Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelTaxDetail[]' to 'BLL.HRSService.HRSHotelTaxDetail'
error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelAmenityCriterion[]' to 'BLL.HRSService.HRSHotelAmenityCriterion'
error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelTaxDetail' to 'BLL.HRSService.HRSHotelTaxDetail[]'
error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelAmenityCriterion' to 'BLL.HRSService.HRSHotelAmenityCriterion[]'
'.  Please see InnerException for more details.]
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +9440287
   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +345
   BLL.HRSService.HRSSoapService.ping(pingRequest request) +0
   BLL.HRSService.HRSSoapServiceClient.BLL.HRSService.HRSSoapService.ping(pingRequest request) in C:\Code\...\BLL\Service References\HRSService\Reference.cs:17311
   BLL.HRSService.HRSSoapServiceClient.ping(HRSPingRequestWrapper ping1) in C:\Code\...\BLL\Service References\HRSService\Reference.cs:17317
   BLL.HRS_Integration.Ping() in C:\Code\...\BLL\General\HRSIntegration.cs:55
   VenueOptions.Test.Page_Load(Object sender, EventArgs e) in C:\Code\...\Test.aspx.cs:24
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +91
   System.Web.UI.Control.LoadRecursive() +74
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

请求终于提出了!

Fiddler 为 PING 显示以下内容:

<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"><ping xmlns="com.hrs.soap.hrs"><pingRequest xmlns=""><credentials><clientType>...</clientType><clientKey>...</clientKey><clientPassword>...</clientPassword><customerKey xsi:nil="true"/></credentials><myHRSCredentials xsi:nil="true"/><echoData>Hello HRS</echoData></pingRequest></ping></s:Body></s:Envelope>

【问题讨论】:

  • 检查堆栈跟踪并查看您的代码在哪里破解。是在请求构建问题还是响应反序列化问题?
  • 我不确定是否诚实,添加了 Stack Trace
  • 出于好奇,wsdl.exe 是否能够生成工作代理?
  • 您是如何解决“错误 CS0030:无法转换类型”的问题的?我明白了,它适用于我调用的方法中甚至没有引用的类型!

标签: c# web-services soap exception-handling


【解决方案1】:

您正在尝试从 .NET 使用 RPC-literal 服务,因此您可能必须将该服务转换为 doc-literal。见MSDN Blog

编辑:更完整的答案

目标是能够使用 doc-literal,但仍然发送相同的消息。让我们关注ping 操作。现在您的 WSDL 的类型定义为:

<complexType name="HRSPingRequest">
    <complexContent>
        <extension base="tns:HRSRequest">
            <sequence>
                <element name="echoData" type="xsd:string"/>
            </sequence>
        </extension>
    </complexContent>
</complexType>

您的消息定义为:

<message name="HRSSoapService_pingRequest">
    <part name="pingRequest" type="tns:HRSPingRequest"/>
</message>

您的绑定定义为:

<binding name="HRSSoapServiceBinding" type="tns:HRSSoapService">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="ping">
        <soap:operation soapAction=""/>
        <input>
            <soap:body namespace="com.hrs.soap.hrs" use="literal"/>
        </input>
        <output>
            <soap:body namespace="com.hrs.soap.hrs" use="literal"/>
        </output>
        <fault name="HRSException">
            <soap:fault name="HRSException" use="literal"/>
        </fault>
    </operation>
</binding>

因此,我们在本地将“rpc”更改为“document”,然后将 WSDL 修复为实际的文档/文字:

<element name="ping" type="tns:HRSPingRequestWrapper" />
<complexType name="HRSPingRequestWrapper">
    <sequence>
        <element name="pingRequest" type="tns:HRSPingRequest" />
    </sequence>
</complexType>
<complexType name="HRSPingRequest">
    <complexContent>
        <extension base="tns:HRSRequest">
            <sequence>
                <element name="echoData" type="xsd:string"/>
            </sequence>
        </extension>
    </complexContent>
</complexType>

...

<message name="HRSSoapService_pingRequest">
    <part name="pingRequest" element="tns:ping"/>
</message>

现在生成此 WSDL 并查看它是否发送 ping 请求。如果您不修复 Response 结构,它可能无法理解返回的内容,但您至少应该看到通过网络发送的请求。您可以使用 SoapUI 加载这两个 WSDL 并查看生成了哪些类型的请求。目标是发送相同的请求,只是使用 document/literal 而不是 rpc/literal。

【讨论】:

  • 感谢您的链接,我们会好好看看。不,我们无法控制 Web 服务生产者。这一切似乎都比应有的复杂。
  • 我们无法将服务转换为 doc-literal,因为我们无法控制服务本身。我们尝试将 [SoapRpcService(Use = SoapBindingUse.Literal)] 添加到所有自动生成的类中,但我们得到了同样的错误。
  • 我认为该博客条目是在谈论仅从服务中获取 WSDL 和模式,将其保存在本地,按照描述对其进行修改,从修改后的本地 WSDL 生成存根,然后仍然将客户端指向原始端点地址。这是一篇旧博文,我从未尝试过,但我认为这就是他们的建议。
  • 你能把服务的 WSDL 和 schema 贴出来吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
相关资源
最近更新 更多