5.2. Consume a .NET web service with gSOAP

5.2.1. Create a client for the Infobel directory web service with gSOAP.

Consuming a .NET web service with gSOAP, even for a more complicated interface, is relatively easy. You will find the web service, used for this demo, up almost 7/24 at infobel web service. This is a phone directory web service, so you can query the service with some name and city and the server will return a list of person matching your criteria. For this example we will make a search for Mr Durant in Brussels (Belgium, Europe).

NoteImportant note
 

The data returned by this web service are obsolete, are from a few years ago and can only be used for demo and testing purpose.

To begin, we have to create the stub as usually with gSOAP, you can refer to the Section called gSOAP client for my JWSDP web service for the use of wsdl2h and soapcpp2. Once the generation of the stub is done we can focus on the client. You will find below the code listed. A simple and easy way to find the function declaration you have to call is to browse the soapClient.c generated file. To find the declaration of the several structures needed you have to browse the infobel.h file (this is the name I choose for the header generated by wsdl2h when I ran the tool). Note here I customized the namespace for this web service in typemap.dat using infobelns.

Example 5-2. SOAP client, for .NET web service, with gSOAP: client.c

To create our client we first have to populate a CQuery object (mapped by gSOAP as infobelns__CQuery). Note here we must use the enum value type correctly initialized for some fields (see the doc on-line of the .NET web service here.

#include "stdio.h"

#include "soapH.h"
#include "InfobelSearchEnginesSoap.nsmap"

int main()
{
  struct soap soap;

  // declare query structure type
  struct _infobelns__Search infnssearch;
  // declare CQuery object
  struct infobelns__CQuery infnsCQ;

  // create the following enum value 
  // to populate the CQuery object
  enum infobelns__Countries enuminfnsc;
  // search in Belgium
  enuminfnsc = infobelns__Countries__aeCountryBE;

  enum infobelns__Services enuminfnss;
  // standard search
  enuminfnss = infobelns__Services__aeSrvStandard;

  enum infobelns__Lang enuminfnsl;
  // search in english
  enuminfnsl = infobelns__Lang__aeLangEnglish;

  enum infobelns__CoordTypes enuminfnsct;
  // Coordinates type in decimal degrees
  enuminfnsct = infobelns__CoordTypes__aeCTWGS;

  // populate the CQuery object
  infnsCQ.login = "infobel";
  infnsCQ.password = "test";
  infnsCQ.country = enuminfnsc;
  infnsCQ.service = enuminfnss;
  infnsCQ.Name = "durant";
  infnsCQ.City = "Bruxelles";
  infnsCQ.Zip = "";
  infnsCQ.XCoord = 0;
  infnsCQ.YCoord = 0;
  infnsCQ.Range = 0;
  infnsCQ.PageStep = 5;
  infnsCQ.Language = enuminfnsl;
  infnsCQ.CoordType = enuminfnsct;

  // assign CQuery to _infobelns__Search.inputQuery
  infnssearch.inputQuery = &infnsCQ;

  // define response structure type
  struct _infobelns__SearchResponse infnsresp;

  soap_init(&soap);

  if(soap_call___infobelns__Search(
  	&soap,
	NULL,
	NULL,
	&infnssearch,
	&infnsresp
	)== SOAP_OK)

  {

    printf("response: %s\n",infnsresp.SearchResult->Status);
    printf("num record: %d\n", infnsresp.SearchResult->Result
      ->NumRecs);
    printf("size CRecord: %d\n",infnsresp.SearchResult->Result
      ->collRecord->__sizeCRecord);

    for(int x=0; x < infnsresp.SearchResult->Result->collRecord
      ->__sizeCRecord; x++)
    {
	printf("\tName: %s\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->Name);
	printf("\tAddress: %s\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->Address);
	printf("\tCity: %s\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->City);
	printf("\tZip: %s\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->Zip);
	printf("\tPhone: %s\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->Phone);
	printf("\tFax: %s\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->Fax);
	if(infnsresp.SearchResult->Result->collRecord->CRecord[x]
          ->collCategory)
	{
	  printf("\tCategory size: %d\n",infnsresp.SearchResult->Result
            ->collRecord->CRecord[x]->collCategory->__sizeCCategory);
	  for(int y=0; y < infnsresp.SearchResult->Result
            ->collRecord->CRecord[x]->collCategory->__sizeCCategory; y++)
	  {
	    printf("\t\tcategory %s code %s\n", infnsresp.SearchResult
	      ->Result->collRecord->CRecord[x]->collCategory->CCategory[y]
              ->description,
	      infnsresp.SearchResult->Result->collRecord->CRecord[x]
              ->collCategory->CCategory[y]->code);
	  }
	}
	printf("\tXCoord: %d\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->XCoord);
	printf("\tYCoord: %d\n", infnsresp.SearchResult->Result
          ->collRecord->CRecord[x]->YCoord);
	printf("\n");
    }
  }

  else
    soap_print_fault(&soap, stderr);

  soap_destroy(&soap);
  soap_end(&soap);
  soap_done(&soap);

  return 0;
}

Once again, you can refer to the Section called Consume a simple remote procedure with gSOAP for a g++ command-line example.