Juan Jose Adan
Juan Jose Adan

Reputation: 135

Send a SOAP Request over HTTP with Angular?

Im starting a new web application project with simple HTML, CSS and Angular. We are using existing Web Services to retrieve data from some servers, one service we are trying to use is a public service: Global Weather SOAP Service

Is there an "easy" way to make the request with Angular? Actually our "test" code is this (with JQuery, still does not work), but would be better to implement the Angular approach with HTTP or RxJS...

import { Injectable } from '@angular/core';
import * as $ from 'jquery';

@Injectable()
export class SoapServiceProvider {

    constructor() { }

    testingSoapRequest() {

        $.ajax({
            url: 'http://www.webservicex.net/globalweather.asmx?op=GetCitiesByCountry',
            data: { CountryName: 'Spain' },
            success: (data) => {
                console.log('Hey, we got a success response', data);
            },
            error: (err) => {
                console.error('We got an error :(', err);
            }
        });

    }

}

I have never used JQuery to make requests of any type (I just use $http in AngularJS and RxJS with Angular), so I really don't know the correct way to make it possible.

Note: There is a library to make Angular SOAP Requests in GitHub but it seems that does not work anymore with new Angular versions.

This is the GitHub Autopulous SOAP link...

Upvotes: 9

Views: 38857

Answers (2)

Sensei James
Sensei James

Reputation: 2695

Yes - there is a way to consume SOAP services in Angular; no third party packages or libraries required. In a nutshell, you set the response type as text, construct an XML document out of the XML text, and (if desired) parse the XML document into JSON format.

Working demo: https://stackblitz.com/edit/angular-soap-test

Here are the steps using Angular 8, although they should also work (or be nearly identical) for Angular 2+:

  1. Request the SOAP resource as text:
     import { HttpClient, HttpParams } from '@angular/common/http';
     import { map } from 'rxjs/operators';

     // ...
     const params = new HttpParams();
     params.set('firstName', 'Peter');
     params.set('lastName', 'Parker');        

     this.http.get(YOUR_SOAP_SERVICE_URL, {responseType: 'text', params })
         .pipe(
           map((xmlString: string)=>{
             const asJson = this.xmlStringToJson(xmlString);
             return asJson;
           }),
           catchError((err)=> {
             console.warn('INT ERR:', err);
             return err;     
           })
         );
  1. Build an XML document out of the JSON string
    xmlStringToJson(xml: string)
    {
      const oParser = new DOMParser();
      const xmlDoc = oParser.parseFromString(xml, "application/xml");
  1. Convert the XML document to JSON
    /* xmlStringToJson(xml: string) */
    // ...
    return this.xmlToJson(xmlDoc);
  }

  // ...

  /**
   * REF: https://davidwalsh.name/convert-xml-json
   */
  xmlToJson(xml)
  {
    // Create the return object
    var obj = {};

    if (xml.nodeType == 1) { // element
      // do attributes
      if (xml.attributes.length > 0) {
      obj["@attributes"] = {};
        for (var j = 0; j < xml.attributes.length; j++) {
          var attribute = xml.attributes.item(j);
          obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
        }
      }
    } else if (xml.nodeType == 3) { // text
      obj = xml.nodeValue;
    }

    // do children
    if (xml.hasChildNodes()) {
      for(var i = 0; i < xml.childNodes.length; i++) {
        var item = xml.childNodes.item(i);
        var nodeName = item.nodeName;
        if (typeof(obj[nodeName]) == "undefined") {
          obj[nodeName] = this.xmlToJson(item);
        } else {
          if (typeof(obj[nodeName].push) == "undefined") {
            var old = obj[nodeName];
            obj[nodeName] = [];
            obj[nodeName].push(old);
          }
          obj[nodeName].push(this.xmlToJson(item));
        }
      }
    }
    return obj;
  }

Upvotes: 1

maninak
maninak

Reputation: 2726

First of all, don't use jQuery, Angular provides you with everything you need out of the box and it's faster and usually more powerful too.

Here's an example Ionic Page, making http requests:

import {Page, Alert, NavController} from 'ionic/ionic';
import {Http} from 'angular2/http';

@Page({
    templateUrl: 'build/pages/home/home.html',
})

export class HomePage {
    constructor(http: Http, nav: NavController) {
        this.http = http;
        this.nav = nav;
    }

    makeGetRequest() {
        this.http.get("https://httpbin.org/ip")
        .subscribe(data => {
            var alert = Alert.create({
                title: "Your IP Address",
                subTitle: data.json().origin,
                buttons: ["close"]
            });
            this.nav.present(alert);
        }, error => {
            console.log(JSON.stringify(error.json()));
        });
    }

    makePostRequest() {
        this.http.post("https://httpbin.org/post", "firstname=Nic")
        .subscribe(data => {
            var alert = Alert.create({
                title: "Data String",
                subTitle: data.json().data,
                buttons: ["close"]
            });
            this.nav.present(alert);
        }, error => {
            console.log(JSON.stringify(error.json()));
        });
    }
}

That logic could be hooked up to a simple template like this one:

<ion-navbar *navbar>
    <ion-title>
        Home
    </ion-title>
</ion-navbar>

<ion-content class="home">
    <button (click)="makeGetRequest()">GET Request</button>
    <button (click)="makePostRequest()">POST Request</button>
</ion-content>

Now since you are using SOAP messaging, you will need to convert JSON to SOAP compatible XML and similarly deconstruct it when you get a response.

I strongly advise you not to use SOAP because, despite the fact that it's an older tecnology, messages are much larger due to more verbose code needed to annotate the same data and most importantly, converting JSON -> XML is slow, especially in Javascript.

That being said, here's a very popular library to convert between the two types.

Upvotes: 1

Related Questions