gpt4 book ai didi

delphi - 如何为 SOAP 客户端完成 XML

转载 作者:行者123 更新时间:2023-12-03 15:52:57 26 4
gpt4 key购买 nike

我正在尝试实现一个 SOAP 客户端来处理此位置 WSDL 文件描述的 Web 服务的加州工资税电子报告:FSET Service 。在此 WSDL 文件中,引用了多个模式,其中一个位于 http://schemas.xmlsoap.org/ws/2004/08/addressing这似乎在我的程序到达 OnBeforeExecute 事件之前就停止了。

为了开始这个项目,我尝试访问 WSDL 文件中声明的 Ping 函数。

我现在刚刚获得一些在 Delphi 中创建 SOAP 客户端的经验。我正在使用 Delphi 2010。这是我为达到这一点所做的事情。我使用 WSDL 导入器导入上述地址的文件。它为我创建了一个名为 fsetservice 的单元。然后,我向项目添加了一个表单,并在其中添加了 HTTPRIO 组件。我将组件的 WSDLLocation 设置为 WSDL 文件的本地副本,在表单上放置几个 TMemos 以捕获请求和响应 header ,并添加代码来执行此操作。然后我设置了一个按钮,并在其 OnClick 事件中编写了以下代码:

procedure TForm1.Button1Click(Sender: TObject);
var sResponse: String;
begin
sResponse := GetFsetServiceSoap.Ping;
end;

当我单击按钮时,在到达 HTTPRIO OnBeforeExecute 事件中的断点之前收到此消息:

Header http://schemas.xmlsoap.org/ws/2004/08/addressing:Action for ultimate recipient is required but not present in the message

我知道每次发帖我们应该只问一个问题,但有时您的了解不足以只问一个好问题:

编辑:为了节省其他有相同问题的人的时间,我将我找到的答案放在这些问题下。

看起来 HTTPRIO 组件可能正在根据 WSDL 中引用的模式检查从 WSDL 文件导入的 XML 的完整性。这看起来很酷,但这是真的吗?

*答案:不正确,至少根据页面底部的注释http://www.tutorialspoint.com/wsdl/wsdl_definition.htm 。根据注释,模式不必实际存在于该位置,它只需唯一标识 WSDL 中使用的模式即可。*

在自动创建(且未修改)的 GetFsetService 函数中,我可以一直单步执行到最后,并且错误发生在返回时,似乎不可能单步进入调用错误的实际流程。有没有办法做到我所缺少的?

回答:我仍然不确定这一点,但似乎答案是否定的。无论如何,尽管从头开始编写此代码会更加乏味,但这比等待 WSDL 向导出现奇迹是一个更好的解决方案。

我是否错过了一些内容,说明我需要实现自动为我创建的 FsetService 接口(interface)?

答案:显然不是。

我在 Marco Cantu 的《掌握 Delphi 2005》一书中看到,Borland 提供了一个应用程序 (WebAppDbg.exe),它允许您查看在特定端口上发送的 HTTP。我尝试过但没有结果。这会有帮助吗?如果有的话,我应该使用哪个端口?

解答:使用 Fiddler2 工具。不错的发现。

如何克服这个错误?

答案:手动完成。

最佳答案

首先,在处理肥皂和 Web 服务时,我会首先将 Fiddler2 和 SoapUI 添加到您的工具库中。

听起来信封标题不完整。根据我使用 D2007 和 WCF Web 服务的经验,Delphi 无法正确构建信封 header ,因此我必须拦截调用并添加如下项目:

procedure TMainForm.MyMessageEnvelopeComplete(Sender: TROSOAPMessage);
begin
Sender.EnvelopeNode.AddAttribute('xmlns:a', 'http://www.w3.org/2005/08/addressing', False);
Sender.HeaderNode.Add('a:Action').Value := 'http://Testservice.Connect/IConnect/Ping';
Sender.HeaderNode.Add('a:To').Value := 'http://testservice-pc:2021/WSConnect';
end;

编辑:

如果您想手动构建肥皂信封和 post 命令,我已经使用以下代码完成了...

procedure TMainForm.Button5Click(Sender: TObject);
procedure HandleError(const errorCode: integer);
var
errorMessage: AnsiString;
begin
SetLength(errorMessage, 256);
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_FROM_HMODULE,
Pointer(GetModuleHandle('wininet.dll')),
errorCode, 0, PChar(errorMessage), Length(errorMessage), nil);
SetLength(errorMessage, StrLen(PChar(errorMessage)));
raise Exception.Create(errorMessage);
end;

function BuildHeader: TStringStream;
begin
result := TStringStream.Create('');
try
result.WriteString('Content-Type: application/soap+xml;charset=UTF-8;action="http://Thermo.Connect/IHCSConnect/Ping"' + sLineBreak);
except
result.Free;
raise;
end;
end;

function BuildBody: TStringStream;
begin
result := TStringStream.Create('');
with result do
try
WriteString('<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">' + sLineBreak);
WriteString('<s:Header>' + sLineBreak);
WriteString('<a:Action>http://Thermo.Connect/IHCSConnect/Ping</a:Action>' + sLineBreak);
WriteString('<a:To>http://thermo-pc:2021/WSHCSConnect</a:To>' + sLineBreak);
WriteString('</s:Header>' + sLineBreak);
WriteString('<s:Body>' + sLineBreak);
WriteString('<Ping xmlns="http://Thermo.Connect">' + sLineBreak);
WriteString('</Ping>' + sLineBreak);
WriteString('</s:Body>' + sLineBreak);
WriteString('</s:Envelope>' + sLineBreak);
except;
result.Free;
raise;
end;
end;

var
InetRoot: HINTERNET;
InetConnect: HINTERNET;
Request: HINTERNET;
begin
InetRoot := InternetOpen('GabeCode', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
try
InetConnect := InternetConnect( InetRoot, 'thermo-pc:2021', 0, '',
'', INTERNET_SERVICE_HTTP, 0, Cardinal(Self));
try
Request := HttpOpenRequest( InetConnect, 'POST', 'WSHCSConnect', 'HTTP/1.1', nil, nil,
INTERNET_FLAG_KEEP_CONNECTION or INTERNET_FLAG_NO_CACHE_WRITE,
0);
try
// build add header items to the post request
with BuildHeader do
try
HttpAddRequestHeaders(Request, PChar(DataString), Length(DataString), HTTP_ADDREQ_FLAG_ADD);
finally
Free;
end;

// build the body of data being posted and send the post
with BuildBody do
try
if not HttpSendRequest(Request, nil, 0, PChar(DataString), Length(DataString)) then
HandleError(GetLastError);
finally
Free;
end;

finally
InternetCloseHandle(Request);
end;
finally
InternetCloseHandle(InetConnect);
end;
finally
InternetCloseHandle(InetRoot);
end;
end;

关于delphi - 如何为 SOAP 客户端完成 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9039607/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com