0

I am using gSOAP for creating a web service to be hosted by a Linux-based system.

I start from the following header file (mytest.h):

#ifndef MYTEST_H
#define MYTEST_H

//gsoap ns service name: mytest
//gsoap ns service namespace: urn:mytest
//gsoap ns service location: http://localhost/mytest

struct ns__testStruct {
    char *field1;
    char *field2;
};

int ns__setdata(struct ns__testStruct data, void);
int ns__getdata(struct ns__testStruct *data);

#endif // MYTEST_H

Then I run the gSOAP compiler for having the corresponding skeleton/stub classes and the corresponding WSDL. I run the compiler using soapcpp2 -e -j mytest.h and I obtain the following WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="mytest"
 targetNamespace="urn:mytest"
 xmlns:tns="urn:mytest"
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:ns="urn:mytest"
 xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:HTTP="http://schemas.xmlsoap.org/wsdl/http/"
 xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
 xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
 xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
 xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

 <schema targetNamespace="urn:mytest"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="urn:mytest"
  xmlns="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="unqualified"
  attributeFormDefault="unqualified">
  <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
 </schema>

</types>

<message name="setdata">
 <part name="data" type="ns:testStruct"/><!-- ns__setdata::data -->
</message>

<message name="getdata">
</message>

<message name="testStruct">
 <part name="field1" type="xsd:string"/><!-- ns__getdata::field1 -->
 <part name="field2" type="xsd:string"/><!-- ns__getdata::field2 -->
</message>

<portType name="mytestPortType">
 <operation name="setdata">
  <documentation>Service definition of function ns__setdata</documentation>
  <input message="tns:setdata"/>
 </operation>
 <operation name="getdata">
  <documentation>Service definition of function ns__getdata</documentation>
  <input message="tns:getdata"/>
  <output message="tns:testStruct"/>
 </operation>
</portType>

<binding name="mytest" type="tns:mytestPortType">
 <SOAP:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
 <operation name="setdata">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:mytest" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
 </operation>
 <operation name="getdata">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:mytest" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:mytest" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
</binding>

<service name="mytest">
 <documentation>gSOAP 2.8.17r generated service definition</documentation>
 <port name="mytest" binding="tns:mytest">
  <SOAP:address location="http://localhost/mytest"/>
 </port>
</service>

</definitions>

Then, using this WSDL I would like to create a simple client in C# (VS2013), but when I try to import the WSDL, Visual Studio fails with the following error:

Custom tool error: Unable to import WebService/Schema. Unable to import binding 'mytest' from namespace 'urn:mytest'. Unable to import operation 'setdata'. The datatype 'urn:mytest:testStruct' is missing.

Why? Any ideas about that?

Morix Dev
  • 2,700
  • 1
  • 28
  • 49

1 Answers1

1

Ok, found the solution here.

I copy/paste the relevant content of the linked page:

class test__X {
long id;
};

int test__f(test__X, bool &);
int test__g(test__X &);

This is a typical example of a missing response wrapper struct in test__g. The problem is that doc/lit style requires test__X to be defined as a schema element since it is the response message of test__g. Because it is also defined as a complexType, a conflict arises.

In this case you must wrap the response parameter(s) in a struct, like: test__g(struct test__gResult { test__X; }&);

Primitive types such as bool do not need to be wrapped, since gSOAP will generate a response message test__fResponse for you.

So, in my case I have to modify my mytest.h as follows:

#ifndef MYTEST_H
#define MYTEST_H

//gsoap ns service name: mytest
//gsoap ns service namespace: urn:mytest
//gsoap ns service location: http://localhost/mytest

struct ns__testStruct {
    char *field1;
    char *field2;
};

int ns__setdata(struct ns__testStruct data, void);
int ns__getdata(struct ns__getDataResponse { struct ns__testStruct d; } *data);

#endif // MYTEST_H
Morix Dev
  • 2,700
  • 1
  • 28
  • 49