Simple SOAP client for Angular 4 based on amazing node-soap library which apparently should only work in a node ambient and not in browsers.
WSDL definitions generator is based on json2ts, which is copied in tools/main.ts and updated a little given initial test cases I worked with.
Still at a very early stage.
npm install --save ngx-soap
Install ngx-soap
:
npm install --save ngx-soap
Import NgxSoapModule in app module:
import { NgxSoapModule } from 'ngx-soap';
...
@NgModule({
imports: [
...,
NgxSoapModule
],
...
})
export class AppModule { }
Let's use the calculator.wsdl
definitions (complete wsdl):
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://tempuri.org/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="Add">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="intA" type="s:int" />
<s:element minOccurs="1" maxOccurs="1" name="intB" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="AddResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="AddResult" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="AddSoapIn">
<wsdl:part name="parameters" element="tns:Add" />
</wsdl:message>
<wsdl:message name="AddSoapOut">
<wsdl:part name="parameters" element="tns:AddResponse" />
</wsdl:message>
<wsdl:portType name="CalculatorSoap">
<wsdl:operation name="Add">
<wsdl:documentation
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">Adds two integers. This is a test WebService. ©DNE Online
</wsdl:documentation>
<wsdl:input message="tns:AddSoapIn" />
<wsdl:output message="tns:AddSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="CalculatorSoap" type="tns:CalculatorSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Add">
<soap:operation soapAction="http://tempuri.org/Add" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="CalculatorSoap12" type="tns:CalculatorSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Add">
<soap12:operation soapAction="http://tempuri.org/Add" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Calculator">
<wsdl:port name="CalculatorSoap" binding="tns:CalculatorSoap">
<soap:address location="http://www.dneonline.com/calculator.asmx" />
</wsdl:port>
<wsdl:port name="CalculatorSoap12" binding="tns:CalculatorSoap12">
<soap12:address location="http://www.dneonline.com/calculator.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The WSDL must be read by the client (e.g with an http request) and its content used with SOAPService service. In the example app the WSDL is served from assets
folder.
Import SOAPService and inject it in your component, then:
-
get WSDL content
-
create the client with the WSDL content definitions
-
call the operation with a JSON input. The client operation method is created dynamically (from the WSDL), therefore it cannot be part of the typescript definitions. You can extend typescript definitions or cast the client to
any
type for instance. The operation returns a callback with the following parameters:- err: error, if any
- wsurl: operation URL from WSDL to be used in the HTTP request
- headers: HTTP headers you may use in the HTTP request
- xml: the input body parsed as xml text to be used in the HTTP request
-
call the operation URL from WSDL with operation parameters (wsurl, xml, headers)
constructor( private http: Http, private soap: SOAPService) { } sum() { // 1. get wsdl content this.http.get('/assets/calculator.wsdl').subscribe(response => { // 2. create the client this.soap.createClient(response.text()).then((client: Client) => { let input = { intA: this.intA, intB: this.intB }; // 3. call the web service operation (client as any).Add(input, (err, wsurl: string, headers: any, xml: string) => { // 4. call the web service operation URL this.http.post(wsurl, xml, { headers: headers }).subscribe( response => { let jsonResponse = client.parseResponseBody(response.text()); this.result = jsonResponse.Body.AddResponse.AddResult; } ); }); }); }); }
See full example app in example
folder.