delphi - 当我在 Delphi 中使用 SOAP 通过 SOAP 将数据远程读取到客户端数据集时,从 TXMLTransform 发送的 XML 解析错误意味着什么?

标签 delphi soap delphi-xe indy tclientdataset

我问another SOAP related question不久前,它需要一个适用于 Delphi XE 及更高版本的可用 Soap 客户端和服务器。

没有人有现成的解决方案,所以我将 Delphi 2007 时代的演示恢复到 Delphi XE 和 XE2 的工作状态。我有演示工作,并且我有一个基于 INDY VCL 表单的服务器(在 Indy 上运行的独立 HTTP 服务器)和一个 Soap 服务器。服务器演示的两个部分是“自定义方法”(正常的 SOAP 函数调用)和“远程数据集”。这是我无法使用的远程数据集。

当我将客户端数据集设置为事件状态时,我在客户端表单中遇到错误,当我在演示客户端中执行此行时,服务器发回异常:

  ClientDataSet1.Open;

这又进入 DBClient.pas 代码,TDataSet.OpenCursor 调用 DoGetRecords 尝试从 ProviderName = 'XMLTransformProvider1' 读取数据>, 通过此 RIO 调用:

  Result := AppServer.AS_GetRecords(ProviderName, Count, RecsOut, Options,
     CommandText, Params, OwnerData);
  // ProviderName = 'XMLTransformProvider1', Count = -1,
  // CommandText = '', Params = NULL, OwnerData = Unassigned

这会因典型的 MessageBox 形式中显示的异常而爆炸:

`ERemotableException: XML Parse error...`. 
    ERemotableException 
    'XML Parse Error:
     Reason: The system cannot locate the object specified.
     '.

Indy Soap 数据模块的服务器端异常调用堆栈如下所示:

xmlutil.DocParseError(TMSDOMDocument($292C994) as IDOMDocument)
xmlutil.LoadDocFromFile(???)
Xmlxform.TXMLTransform.GetData
Xmlxform.TXMLTransformProvider.InternalGetRecords(???,???,[grMetaData],'',Null)
Provider.TCustomProvider.DoGetRecords(-1,0,1,'',Null,Null)
Provider.TCustomProvider.GetRecords(???,0,1,'',Null,Null)
SOAPDm.TSoapDataModule.GetRecords('XMLTransformProvider1',-1,0,1,'',Null,Null)
SOAPDm.TSoapDataModule.SAS_GetRecords('XMLTransformProvider1',-1,0,1,'',Null,Null)
Invoker.TInterfaceInvoker.Invoke(???,('IDataMod', 'DataMod_U', (('', ccReg, 0, 0, nil, nil, (), False), ('', ccReg, 0, 0, nil, nil, (), False), ('', ccReg, 0, 0, nil, nil, (), False), ('SAS_ApplyUpdates', ccStdCall, 3, 5, $401314, $628D50, (([pfConst], 'ProviderName', $4012DC), ([pfReference], 'Delta', $401314), ([], 'MaxErrors', $4010A0), ([pfOut], 'ErrorCount', $4010A0), ([pfVar,pfReference], 'OwnerData', $401314), ([], '', nil)), True), ('SAS_GetRecords', ccStdCall, 4, 7, $401314, $628D50, (([pfConst], 'ProviderName', $4012DC), ([], 'Count', $4010A0), ([pfOut], 'RecsOut', $4010A0), ([], 'Options', $4010A0), ([pfConst], 'CommandText', $4012DC), ([pfVar,pfReference], 'Params', $401314), ([pfVar,pfReference], 'OwnerData', $401314), ([], '', nil)), True), ('SAS_DataRequest', ccStdCall, 5, 2, $401314, $628D50, (([pfConst], 'ProviderName', $4012DC), ([pfReference], 'Data', $401314), ([], '', nil)), True), ('SAS_GetProviderNames', ccStdCall, 6, 0, $40BC38, $628D50, (([], '', nil)), True), ('SAS_GetParams', ccStdCall, 7, 2, $401314, $628D50, (([pfConst], 'ProviderName', $4012DC), ([pfVar,pfReference], 'OwnerData', $401314), ([], '', nil)), True), ('SAS_RowRequest', ccStdCall, 8, 4, $401314, $628D50, (([pfConst], 'ProviderName', $4012DC), ([pfReference], 'Row', $401314), ([], 'RequestType', $4010A0), ([pfVar,pfReference], 'OwnerData', $401314), ([], '', nil)), True), ('SAS_Execute', ccStdCall, 9, 4, nil, $628D50, (([pfConst], 'ProviderName', $4012DC), ([pfConst], 'CommandText', $4012DC), ([pfVar,pfReference], 'Params', $401314), ([pfVar,pfReference], 'OwnerData', $401314), ([], '', nil)), True), ('CustomMethod', ccStdCall, 10, 0, $4012CC, $62E668, (([], '', nil)), True)), (45872836, 16917, 16768, (153, 166, 192, 149, 84, 207, 120, 216)), $62E668, $628D50, 10),4,$2942270)
SOAPPasInv.TSoapPascalInvoker.Invoke(???,???,'',$28F3700,$28F36A0,???)
SOAPHTTPPasInv.THTTPSoapPascalInvoker.DispatchSOAP('/SOAPDMServerWAD.Sample/soap/IDataMod',???,$28F3700,$28F36A0,btSoap)
WebBrokerSOAP.THTTPSoapDispatcher.DispatchRequest(???,???,$29421C8)
HTTPApp.DispatchHandler($28E4140,THTTPSoapDispatcher($291687C) as IWebDispatch,$290FEA0,$29421C8,False)
HTTPApp.TCustomWebDispatcher.DispatchAction($290FEA0,$29421C8)
HTTPApp.TCustomWebDispatcher.HandleRequest(???,???)
HTTPApp.TDefaultWebAppServices.InvokeDispatcher
HTTPApp.TDefaultWebAppServices.HandleRequest
WebReq.TWebRequestHandler.HandleRequest($290FEA0,$29421C8)
IdHTTPWebBrokerBridge.TIdHTTPWebBrokerBridgeRequestHandler.Run(???,$28851B0,???)
IdHTTPWebBrokerBridge.TIdHTTPWebBrokerBridge.DoCommandGet(???,???,???)
IdCustomHTTPServer.TIdCustomHTTPServer.DoExecute($293AB30)
IdContext.TIdContext.Run
IdTask.TIdTask.DoRun
IdThread.TIdThreadWithTask.Run
IdThread.TIdThread.Execute
Classes.ThreadProc($28A1FE0)

我相信正在发生的事情是我们收到了一个空的 HTTP 响应。如果没有任何效果,并且我们正在访问的 HTTP url 不起作用,这对我来说是完全有意义的。我们正在访问的网址是,并且可以通过网络浏览器访问:

http://localhost:8088/?intf=IDataMod

返回到客户端并导致错误消息的 XML 如下所示:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
 <SOAP-ENV:Body>
  <SOAP-ENV:Fault>
   <faultcode>SOAP-ENV:Server</faultcode>
   <faultstring>XML Parse Error:'#$D#$A#$D#$A'Reason: The system cannot locate the object specified.'#$D#$A#$D#$A#$D#$A'</faultstring>
   <faultactor/>
</SOAP-ENV:Fault>
</SOAP-ENV:Body></SOAP-ENV:Envelope>

我的问题是:该 SOAP 错误的真正含义是什么,为什么会发生,以及如何修复它?

最佳答案

在这种情况下,意味着客户端已经收到服务器端发生异常的通知。由于服务器端的异常是由演示代码问题引起的,解决办法是修复演示服务器,使其正常运行。

对于 Delphi 2007 附带的 SOAP 服务器,在 SoapDataModule 示例文件夹中,其问题在于它没有错误检查;如果它无法加载 XML 示例数据(因为数据文件夹已移动或丢失),那么它会在服务器端引发未处理的异常。

SOAP 具有为您自动化工作的良好特性;客户端收到我们收到 SOAP 调用的通知,并且我们返回 SOAP 异常而不是真正的响应。这里不能责怪 SOAP,Delphi SOAP RTL 实际上使用起来非常友好。但这里需要注意的基本点是,soap 服务的实现者应该在 soap 服务器启动时对其进行一些健全性检查,以便可以在错误对 SOAP 请求造成致命影响之前对其进行修复。

吸取的教训;当您构建 SOAP 服务器时,请考虑将配置错误处理和 fatal error 检测作为第一个 SOAP 服务器 session 之前的启动任务。

关于delphi - 当我在 Delphi 中使用 SOAP 通过 SOAP 将数据远程读取到客户端数据集时,从 TXMLTransform 发送的 XML 解析错误意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9825614/

相关文章:

delphi - 使用 DeHL 集合库中的 THashSet 时出错

delphi - 为什么 FreeAndNil 实现在 Free 之前执行 Nil ?

c# - 如何消费https wcf服务?

java - 如何打印 SOAPMessage

java - Java代码无法访问Web Service,但在Chrome中可以正常看到其wsdl

delphi - 编译器警告 "return value might be undefined"

delphi - 将 Delphi 2007 字符串加密例程转换为 Delphi XE

delphi - Delphi TBitBtn白色层

delphi - 在最小化或非事件表单中模拟鼠标点击

delphi - 在64位系统中如何从PID获取系统的进程路径?