Tech Articles


Call SOAP Web Services Using HTTPClient Object


Since PowerBuilder 2017 R2, we have a new HTTPClient object, which is a base object for sending HTTP requests and receiving HTTP responses from a resource identified by a URI. Compared to the Inet object, the HTTPClient object is easier to use and supports more methods (Get/Post/Put/Delete) and more SSL protocols (TLS 1.0, TLS 1.1, TLS 1.2, SSL 2.0, and SSL 3.0).

Among other things, the HTTPClient can be also used to consume SOAP Web services. This is particularly useful as the Web Service Proxy has many limitations and defects calling SOAP Web services such as not supporting TLS 1.2. This article is to show how you can use the new HTTPClient to call your existing SOAP Web services instead. 

Call SOAP Web services using Web Service Proxy

As a background story, let's revisit how PB consumes a SOAP Web service in the past. Firstly, you need to create a Web Service Proxy and then associate it with the pbsoapclient170.pbd or import pbsoapclient170.pbx.

Then in PB IDE, you instantiate the PB proxy with the SOAP Web service link and use the SOAPConnection object to call the associated Web service methods. 

Here is the sample code:

SoapConnection conn // Define SoapConnection

n_webservicesoap proxy_obj // Declare the proxy

long rVal

integer li_rtn

string str_endpoint

str_endpoint = "http://localhost/invoice/n_webservice.asmx?WSDL"

conn = create SoapConnection  //Instantiate connection

rVal = Conn.CreateInstance(proxy_obj, "n_webservicesoap", str_endpoint)

// Create proxy object

try

  li_rtn = proxy_obj.of_add(2)     //invoke Web service of_add method.

catch(SoapException e)

   messagebox("Error", "Cannot invoke Web service")

   // Error handling  

end try

destroy conn

Call SOAP Web services using HTTPClient

With the new HTTPClient object, we have a better option to call SOAP Web service.

1. Find the Correct SOAP Web service parameters

Open the SOAP Web service on IE as shown below. Copy the associated SOAP sample request. Refer to the highlighted content below. (If you don’t see this content, please contact your service provider to get such a sample request.)

Use a third party tool like Postman to verify what protocol and arguments you need to use to successfully call the Web service API.

Note: You need to replace the argument in the XML you copied in the previous step with the real argument to call the API. In this sample, we replace the word short (data type of the parameter ai_test for the of_add method) with the real argument(2).

2. Use the HTTPClient object to call the API.

After you verified successfully with Postman, apply the same protocol and arguments to HTTPClient object in your PB code. 

Here is the sample code:

httpClient lo_client

integer li_ret , i , li_StatusCode

String lo_xml_request

string ls_url

string ls_data

string ls_body

string ls_ret

 

ls_url ="http://localhost/invoice/n_webservice.asmx"

ls_body = '<?xml version="1.0" encoding="utf-8"?>'+&

'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '+&

'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'+&

'  <soap:Body>'+&

'    <of_add xmlns="http://tempurl.org">'+&

'      <ai_test>2</ai_test>'+&

'    </of_add>'+&

'  </soap:Body>'+&

'</soap:Envelope>'

 

lo_client = Create httpClient

lo_client.SetRequestHeader("Content-Type", "text/xml")

lo_client.sendrequest('POST',ls_url,ls_body)

 

li_StatusCode = lo_client.GetResponseStatusCode()

ls_ret = lo_client.GetResponseStatusText( )

li_ret = lo_client.getresponsebody(  ls_data)

destroy lo_client

The new approach for calling SOAP Web services is clean and simple, and it gives you more flexibility than the previous approach. We hope that you will find this article useful in your implementation of the consumption of SOAP Web services in your applications. 

Note: If you want to use the PBDOM Object to build the XML content, you can refer to this knowledgebase.

Call simple ASP.NET Web Service using HTTPClient

1. Build a Web Service

Build a simple Web Service project based on .NET Framework, then directly add a Web Service (ASMX) object WebService into this project. 

Here below is the C# code for reference:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{

    public WebService()
    {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }

    [WebMethod]
    public int Add(int x, int y)
    {
        return x + y;
    }
}

2. Find the correct arguments to call the WebService 

This sample Web Service has only two APIs. One is the HelloWorld method that returns a string and the other one is the Add method that has two int type input parameters and returns an int value.

First of all, use a third party tool to verify what protocol and arguments you need to use to call this Web Service API.

For example, we use Postman to verify it here.

From the result you can see the request format of the current API is different from the one we introduced in the previous section. The Content-Type should be set to application/x-www-form-urlencoded instead of application/xml.

3. Use the HTTPClient object to call the Add method of this API.

After you verified successfully with Postman, apply the same request protocol to the HTTPClient object in your PB code. 

Here below is the sample code:

httpClient 	lo_client
integer 	li_ret ,  li_StatusCode
string 		ls_url 
string 		ls_data
string 		ls_body 
string 		ls_ret

ls_url ="http://localhost:53326/WebService.asmx/Add"			
ls_body="x=7&y=8"
 
lo_client = Create httpClient
lo_client.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
lo_client.sendrequest('POST',ls_url,ls_body)

li_StatusCode = lo_client.GetResponseStatusCode()
ls_ret = lo_client.GetResponseStatusText( )
li_ret = lo_client.getresponsebody(  ls_data)
destroy lo_client
Comments (29)
Thursday, Apr 18 2019

Hi Tom,

Thank you for sharing this knowledge but I have some questions:

Could you please explain how to "Use a third party tool like Postman to verify what protocol and arguments you need to use to successfully call the Web service API."?
I've downloaded PostMan but I don't see what to do with it to "get the protocol and arguments". Then I neither see where to put the "protol" once I would have gotten it.

Also: Is this faster then using the traditional way with Soap? Sorry for my ignorance and thank you.

Comment was last edited 5 years ago by Miguel Leeuwe
0
Friday, Apr 19 2019

Hi Miguel,

We mentioned Postman mainly for you to test and verify if you can directly call the API from your service provider successfully on your machine.

It would also help you to understand how to set up the parameters for HTTPClient. If your service provider has already provided you a complete API documentation, you can ignore this part.

Regrading how to use Postman, we suggest that you do a Google search or refer to the tutorial on Postman’s official site.

BTW, HTTPClient object is for sure much better than the traditional way with SOAP both in terms of flexibility and efficiency. You can give it a try.

Regards,

Tom Jiang

0
Friday, Apr 19 2019

Thank you.
regards,
Miguel

0

Monday, May 06 2019

Hi Tom

I was trying to migrate Soap client with .NET assembly from PowerBuilder 11.5 where it was running perfectly.
In PB 2017 R3 Web Service proxy was deployed succesfully, but when I call web service method, raised SoapException:
The SoapClient doesn't support .NET proxy

Are you still supporting .NET assembly for web services?

Sergey

0
Wednesday, May 08 2019

1. Please refer to PB help or the following link. SOAPClient is obsoleted, which means it is no longer eligible for technical support and will not be enhanced.
https://www.appeon.com/support/documents/appeon_online_help/pb2017r3/application_techniques/ch35s03.html#d0e23597

2. About supporting .NET assembly for web services
PB 2017 is inherited from PB 12.6. No restrictions or changes are made on this feature. In other words, if it works in PB 12.6, it should still work in PB 2017. But if you do have problem using it, we suggest that you use HTTPClient to rewrite your function.

0
Wednesday, May 08 2019

Thank you for reply Tom.

Yes, I already tested new HTTPClient and even make nice visual interface to work with it.

And yes, it's good to have full control for making http request and parsing http response.

(Sometime when I was stacked with old SoapClient with complex Web Servicis, I was thinking that will be nice to have naked HttpClient and here is it ))

From the other side you may need more coding and may be use PBDOM for parsing complex response body.

0
Thursday, May 16 2019

Hi Sergey,

Are you able to use HttpClient in .Net Assembly?
We are facing an issue using webservice proxy to call WebService on .Net Assembly, but there is a performance issue, it takes around 1.5 second to make a call even it is just a 'Helleworld' like program, so we want to use HttpClient which is much faster, but .Net assembly doesn't support it.

0

Tuesday, May 21 2019

How do you create the web service? You can't call one until it exists.

0
Sunday, May 26 2019

Hi Roland,

The intention of this article is to provide a solution for consuming existing SOAP web services especially when it requires the TLS1.2 protocol.

If you don't have the web service, We highly recommend that you try our coming C# Web API solution. Please refer to the section on SnapDevelop on this page https://www.appeon.com/documents. There are step by step tutorials teaching you how to create and consume web APIs.

0

Wednesday, Jun 05 2019

I am planning to migrate all our web service client projects to the new httpclient object from the traditional .NET/EasySoap proxy way. The main reason is the death knell tolled for TLS 1.0, and the somewhat slow performance of the .NET projects.
However, one of the nice features of those traditional projects was the ability to generate all the data contract nvos needed for complex web services. So far, I like to use the .NET project for generating these nvos from the wsdl, later supplying them with my own xml serializer/de-serializer methods.

I hope this functionality for generating nvo's will be kept in some way?

Comment was last edited 5 years ago by Sverre Tvedt
1
Thursday, Jun 13 2019

Hi Sverre, the functionality for generating NVOs will still be kept for the traditional projects. The new HTTPClient object is just a general purpose tool to handle HTTP reuqests. There are also new objects like RESTClient, JSONParser tailored to RESTful web services. But at this moment, there is no plan for enhancing the old proxy project for handling SOAP web services.

0
Saturday, Jun 15 2019

You can force TLS 1.2 via the registry with the .Net/East Soap Proxy. This is a fallacy.

https://support.microsoft.com/en-us/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi

0
Tuesday, Jul 16 2019

Sure but the .NET/EasySoap is not supported by Appeon. This article outlines a supported approach to call legacy SOAP Web services.

0

Friday, Jun 28 2019
0

Tuesday, Jul 02 2019

Can I set the HTTP header using the HTTPClient object approach ?

0

Monday, Sep 16 2019

Till now we were calling web service by web proxy. Now I was trying to call by HTTPClient Object.
But the web service is returning a structure. But by HTTP client we are only getting a string, so any way we can resolve it?

0

Monday, Feb 03 2020

We are using PB 2017 R3 and wanted to implement new WebCall Services..
For the SOAP Header, I need to Pass WS Security with Token, Username and password.

I tested with SOAP UI and it returns value as expected, but i see Header generated looks like this
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-7A8B6A17C01D44B5BF15797123635963">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">sgHKfLi68IGQSbtl/TAS7w==</wsse:Nonce>
<wsu:Created>2020-02-03T17:17:32.658Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>

I tried with Postman but no luck to get a result back.
Is there way to generate this Security before calling.
I tried both Web service Proxy and HTTP client method but get "User Not Authenticated Error"

Any help on this would be great help.

Thanks

0
Tuesday, Feb 04 2020

Thanks Lee..
All the Examples links provided are OAuth and REST services.

I am looking for Basic Authentication with WS Security.

0
Wednesday, Feb 05 2020

Hi Sakthivel,

For Basic Authentication with HttpClient or RestClient object, you can refer to the following links:
https://docs.appeon.com/appeon_online_help/pb2019r2/application_techniques/ch19s01.html
https://www.appeon.com/standardsupport/search/view?id=1667

Regards,

1
Wednesday, Feb 05 2020

Thanks Lee..
I was missing the Coder Object part.
Once i created like you specified in this post https://www.appeon.com/standardsupport/search/view?id=1667,

Service calls are working as expected using HTTPClient.
So I have to use Only HTTPclient in this type of Authentication.

SoapConnection doesn't work as no way to Pass the Generated Token.
or using conn.SetBasicAuthentication (string domain, string userID, string password) also doesn't seem to work. I get "Could not authenticate user"

One disadvantage in HTTPConnection is, we need to generate XML for each web service methods to call (But no need to Create Proxy Object) where as SOAPConnection is easy to call the method as it generated in the Proxy Object.

Is my Understanding Correct?

Appreciate your help on this.

0
Thursday, Feb 06 2020

Yes, your understanding is correct!
Regards,

1

Monday, Sep 19 2022

Here an example of HTTPClient used inside click button:

w_httpclient_test
---


httpClient lo_client
integer li_ret // 1
integer li_StatusCode // 200
string ls_url // endpoint
string ls_data // response
string ls_body // xml to send
string ls_ret // OK

ls_url ="https://www.dataaccess.com/webservicesserver/NumberConversion.wso"
ls_body = ''
ls_body += '<?xml version="1.0" encoding="utf-8"?>'
ls_body += '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
ls_body += ' <soap:Body>'
ls_body += ' <NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/">'
ls_body += ' <ubiNum>124</ubiNum>'
ls_body += ' </NumberToWords>'
ls_body += ' </soap:Body>'
ls_body += '</soap:Envelope>'

lo_client = Create httpClient
lo_client.SetRequestHeader("Content-Type", "text/xml")
lo_client.sendrequest('POST', ls_url, ls_body)

li_StatusCode = lo_client.GetResponseStatusCode()
ls_ret = lo_client.GetResponseStatusText( )
li_ret = lo_client.getresponsebody( ls_data)
destroy lo_client


messagebox("Service response", ls_data)


---

I hope it will be a good help for someone.
Example inspired from POSTMAN documentation: https://documenter.getpostman.com/view/8854915/Szf26WHn

0
Wednesday, Oct 05 2022

thank you

0

Saturday, Jul 29 2023

The Soap .NET Proxy transparently solved the serialization of objects to xml. Calling a WS SOAP with HTTPClient when you have to send complex multi-level objects makes the serialization task a hard job, when in previous versions of PB it was all solved. Although SOAP does not meet new security standards, they should have kept this functionality in PB 2022!

1

Find Articles by Tag

RibbonBar Builder Validation COM CI/CD Mobile RESTClient Windows OS Android License XML OAuth 2.0 InfoMaker Migration SVN Excel PowerServer Web Event Handler Event Handling RichTextEdit Control Export PostgreSQL SnapDevelop Encoding SqlModelMapper ODBC WinAPI Jenkins .NET DataStore Expression SQL DataWindow Service PowerBuilder Compiler Source Control Transaction Elevate Conference MessageBox Class DataWindow JSON Authentication PowerBuilder Script Export JSON TreeView Performance PDFlib Bug Debug Windows 10 Icons Icon Messagging DevOps CoderObject SDK SnapObjects UI Modernization Encryption Model API OLE DLL Database Table Data Database Object Design Menu Database RibbonBar DragDrop JSONParser 64-bit NativePDF Array Automated Testing External Functions HTTPClient PowerBuilder (Appeon) Filter .NET Assembly Authorization Sort JSON Installation Branch & Merge Testing Repository PDF .NET Std Framework DataType Deployment Trial SOAP OAuth Platform PBDOM TFS Linux OS Database Table Schema Azure Database Painter Web Service Proxy PostgreSQL ODBC driver Import Debugger UI Application Open Source PowerScript (PS) Graph UI Themes Error Import JSON Debugging TortoiseGit GhostScript PowerServer Mobile Stored Procedure iOS Database Table Source Code Syntax JSONGenerator Resize REST File Charts Database Profile Database Connection SqlExecutor Text Event Variable Interface CrypterObject SQL Server PFC Window WebBrowser Data BLOB TLS/SSL C# Outlook Oracle 32-bit Web API OrcaScript Git Configuration IDE ActiveX