Reputation: 41
I need to consume a SOAP 1.2 web service which uses WS-Security. The platforms I use at work are Delphi 10.2 Tokyo and .Net Core. Neither of these seem to work.
When trying with Delphi 10.2 Tokyo's built in WSDL importer (using SOAP 1.2 with Indy), my requests are sent without any SOAP header information. This invalid request throws the error Connection reset by peer.
When trying with .Net Core (using WCF Web Service Reference Provider) I get the error: System.PlatformNotSupportedException: 'TransportSecurityBindingElement.BuildChannelFactoryCore is not supported.'
Presumably due to the required feature not being supported by .Net Core yet: https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.0.0.md (Security.Message isn't supported)
Below is the WSDL. I have trimmed unnecessary XML from this file, and replaced the actual company name with Example. Hopefully this will give enough of an idea of what the WSDL policies/requirements are.
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:i0="http://tempuri.org/"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="www.example.com/ExampleService"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsa10="http://www.w3.org/2005/08/addressing"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="ExampleService"
targetNamespace="www.example.com/ExampleService">
<wsp:Policy wsu:Id="ExampleAPI_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:EndorsingSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:BootstrapPolicy>
<wsp:Policy>
<sp:SignedParts>
<sp:Body />
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:TransportBinding>
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens>
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss11>
<wsp:Policy />
</sp:Wss11>
<sp:Trust10>
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust10>
</wsp:Policy>
</sp:BootstrapPolicy>
</wsp:Policy>
</sp:SecureConversationToken>
</wsp:Policy>
</sp:EndorsingSupportingTokens>
<sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy />
</sp:Wss11>
<sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust10>
<wsaw:UsingAddressing />
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="ExampleAPI2_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy />
</sp:Wss10>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsdl:types>
<!-- trimmed away types -->
</wsdl:types>
<!-- trimmed away messages -->
<wsdl:portType name="IAPIService">
<!-- trimmed away operations -->
</wsdl:portType>
<wsdl:binding name="ExampleAPI" type="tns:IAPIService">
<wsp:PolicyReference URI="#ExampleAPI_policy" />
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<!-- trimmed away operations -->
</wsdl:binding>
<wsdl:binding name="ExampleAPI2" type="tns:IAPIService">
<wsp:PolicyReference URI="#ExampleAPI2_policy" />
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<!-- trimmed away operations -->
</wsdl:binding>
<wsdl:service name="ExampleService">
<wsdl:port name="ExampleAPI" binding="tns:ExampleAPI">
<soap12:address location="https://example.com/apps/api/APIService.svc" />
<wsa10:EndpointReference>
<wsa10:Address>https://example.com/apps/api/APIService.svc</wsa10:Address>
</wsa10:EndpointReference>
</wsdl:port>
<wsdl:port name="ExampleAPI2" binding="tns:ExampleAPI2">
<soap:address location="https://example.com/apps/api/APIService.svc/endpoint2" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Upvotes: 1
Views: 459
Reputation: 41
.NET Framework has full support for the SOAP service. I've developed a .NET Framework app in C#, and built a DLL which can be used by Delphi, .NET Core, etc. It's a bit of a roundabout solution, yet the easiest one I could find.
Accessing services in C#: https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
Export DLL functions: Is is possible to export functions from a C# DLL like in VS C++?
Upvotes: 0
Reputation: 1106
There's no specific 'best' platform to consume a webservice. However, some platforms support the automatic generation of proxy classes better than others.
When trying with Delphi 10.2 Tokyo's built in WSDL importer (using SOAP 1.2 with Indy), my requests are sent without any SOAP header information.
I don't have experience with .NET Core, but when using Delphi 10.2 you need to manually add (Send) the SOAP header before you send your request.
This can be done by casting the webservice instance to ISOAPHeaders
Example:
procedure TestSendHeader;
var
MyService: IMySoapWebservice;
header : TMySoapHeader;
begin
MyService := GetMySoapService();
(MyService as ISOAPHeaders).OwnsSentHeaders := True;
// Create header object
header := TMySoapHeader.Create;
// Fill header data
// header.xyz := ;
// 'Send' header with the request
(MyService as ISOAPHeaders).Send(header);
MyResponse := MyService.DoMyRequest();
end;
Setting OwnsSentHeaders
to true
wil free up the created header object, after the request has been sent.
NOTE: you have to 'Send' the header each time you make a request:
// 'Send' header with the request 1
(MyService as ISOAPHeaders).Send(header);
MyResponse := MyService.DoMyRequest1();
// 'Send' header with the request 2
(MyService as ISOAPHeaders).Send(header);
MyResponse := MyService.DoMyRequest2();
In this case, don’t set OwnsSentHeaders
to true
and free the header object after you’re done, sending requests.
Upvotes: 3