Web Service returning xs:choice as return type in C++ .NET

G

Guest

Hi,

I want to consume a Web Service that returns a choice, but my C++ client
always receives the same returned type. On the other hand, when I am using a
Java client, it is working fine (of course, the generated proxy is not the
same).

When I am looking at the C++ generated code, it seems fine, but when I am
executing the code, I always get the first choice type.

Do someone already used a returned choice in C++ ?

(I am using Visual Studio 2003).


Here is the execute code:

// -------------------------
// My test code
// -------------------------
Object *queryResult = webService->queryMatchingPersonsByTraits(
fillRequestType(condition), szProductID, Convert::ToString(iMaxReturnRow),
totalNumberOfMatches, timestamp );

Query::personQueryResponseTypeMatchingProfiles *profiles =
dynamic_cast<Query:: PersonQueryResponseTypeMatchingProfiles *>(queryResult);
if ( profiles == NULL )
{
Query::personQueryResponseTypeError* error =
dynamic_cast<Query::personQueryResponseTypeError*> (queryResult);
String *value = error->Value;
}

//I never receive a PersonQueryResponseTypeMatchingProfiles in my C++ code,
but I am receiving some in the Java code.


//---------------------------
// Generated Proxy method declaration
//---------------------------
public:
[System::Web::Services::protocols::SoapDocumentMethodAttribute(S"http://www.openuri.org/queryMatchingPersonsByTraits",
RequestElementName=S"PersonQueryRequest",
RequestNamespace=S"http://.../personqueryrequest",
ResponseElementName=S"PersonQueryResponse",
ResponseNamespace=S"http://.../personquery",
Use=System::Web::Services::Description::SoapBindingUse::Literal,
ParameterStyle=System::Web::Services::protocols::SoapParameterStyle::Wrapped)]
[returnvalue: System::Xml::Serialization::XmlElementAttribute(S"Error",
__typeof(Query::personQueryResponseTypeError))]
[returnvalue:
System::Xml::Serialization::XmlElementAttribute(S"MatchingProfiles",
__typeof(Query::personQueryResponseTypeMatchingProfiles))]
System::Object *
queryMatchingPersonsByTraits(Query::personQueryRequestTypeProfileData *
ProfileData, [System::Xml::Serialization::XmlAttributeAttribute]
System::String * SystemID,
[System::Xml::Serialization::XmlAttributeAttribute(DataType=S"integer")]
System::String * MaxNumMatches,
[System::Xml::Serialization::XmlAttributeAttribute(DataType=S"integer")]
System::String * & TotalNumberOfMatches,
[System::Xml::Serialization::XmlAttributeAttribute] System::DateTime&
Timestamp);

//---------------------------
// Generated Proxy method definition
//---------------------------
inline System::Object *
Person::queryMatchingPersonsByTraits(Query::personQueryRequestTypeProfileData
* ProfileData, [System::Xml::Serialization::XmlAttributeAttribute]
System::String * SystemID,
[System::Xml::Serialization::XmlAttributeAttribute(DataType=S"integer")]
System::String * MaxNumMatches,
[System::Xml::Serialization::XmlAttributeAttribute(DataType=S"integer")]
System::String * & TotalNumberOfMatches,
[System::Xml::Serialization::XmlAttributeAttribute] System::DateTime&
Timestamp) {
System::Object* __mcTemp__1[] = new System::Object*[3];
__mcTemp__1[0] = ProfileData;
__mcTemp__1[1] = SystemID;
__mcTemp__1[2] = MaxNumMatches;
System::Object * results[] =
this->Invoke(S"queryMatchingPersonsByTraits", __mcTemp__1);
TotalNumberOfMatches = (__try_cast<System::String * >(results[1]));
Timestamp = (*__try_cast<__box System::DateTime * >(results[2]));
return (__try_cast<System::Object * >(results[0]));
};


// -------------------------------
// XML part
// -------------------------------
…
<xs:element name="QueryResponse" type="pq:QueryResponseType">
</xs:element>
<xs:complexType name="QueryResponseType">
<xs:choice>
<xs:element name="Error">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="pq:ErrorType" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="Profiles">
<xs:complexType>

</xs:complexType>
</xs:element>
</xs:choice>

</xs:complexType>
<xs:simpleType name="ErrorType">
<xs:restriction base="xs:string">
<xs:enumeration value="client"/>
<xs:enumeration value="server"/>
</xs:restriction>
</xs:simpleType>
…
 
G

Gary Chang[MSFT]

Hi dgaucher,
I want to consume a Web Service that returns a choice, but my C++ client
always receives the same returned type.

What's the return "xs:choice" here, a custom type you defined in your
webservice application, something like a enum type?

By the way, do you have tried to use other .NET language code(e.g. C#) to
consume the Web Service, is it OK?


Thanks for your understanding!

Best regards,

Gary Chang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
 
G

Guest

Hy Gary
By the way, do you have tried to use other .NET language code(e.g. C#) to
consume the Web Service, is it OK?

I have just tried with C# and I am having the same result as in C++. If you
look at the schema, you will find that I should receive an “Error†or a
“MatchingProfilesâ€. What I am getting from either C# or C++ is always the
“Errorâ€. When the Web Service effectlively returned an “Errorâ€, it is filled
properly, but when it returns a “MatchingProfilesâ€, I am getting an “Errorâ€
with the default data in.
What's the return "xs:choice" here, a custom type you defined in your
webservice application, something like a enum type?

Effectively, the return is a complex type.
//--------------------------------------------------------------------------
<xs:complexType name="PersonQueryResponseType">
<xs:choice>
<xs:sequence>
<xs:element name="Error">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="pq:ErrorType" use="required"/>

</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="MatchingProfiles">
<xs:complexType>
<xs:sequence>
<xs:element name="UnknownMatchingPerson" minOccurs="0"
maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Alias" minOccurs="0" maxOccurs="10">

<xs:complexType>
<xs:attribute name="FirstName" type="xs:string"
use="optional"/>
<xs:attribute name="LastName" type="xs:string"
use="optional"/>
<xs:attribute name="MiddleName" type="xs:string"
use="optional"/>
<xs:attribute name="NameSuffix" type="xs:string"
use="optional"/>
<xs:attribute name="AliasDOB" type="xs:date"
use="optional"/>
<xs:attribute name="AliasSSN" type="xs:string"
use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="ScarsMarksTattoos" minOccurs="0"
maxOccurs="10">
<xs:complexType>
<xs:attribute name="SMTNCICCode" type="xs:string"
use="optional"/>
<xs:attribute name="SMTDescription" type="xs:string"
use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="ConfidenceLevel" type="xs:double"
use="required"/>
<xs:attribute name="MPI" type="xs:string" use="required"/>

<xs:attribute name="MNI" type="xs:string" use="required"/>

<xs:attribute name="FirstName" type="xs:string"
use="optional"/>
<xs:attribute name="LastName" type="xs:string"
use="optional"/>
<xs:attribute name="MiddleName" type="xs:string"
use="optional"/>
<xs:attribute name="NameSuffix" type="xs:string"
use="optional"/>
<xs:attribute name="SSN" type="xs:string" use="optional"/>

<xs:attribute name="StateID" type="xs:string" use="optional"/>

<xs:attribute name="DateOfBirth" type="xs:date"
use="optional"/>
<xs:attribute name="CityOfBirth" type="xs:string"
use="optional"/>
<xs:attribute name="CountyOfBirth" type="xs:string"
use="optional"/>
<xs:attribute name="StateOfBirth" type="xs:string"
use="optional"/>
<xs:attribute name="CountryOfBirth" type="xs:string"
use="optional"/>
<xs:attribute name="Gender" type="xs:string" use="optional"/>

<xs:attribute name="Race" type="xs:string" use="optional"/>

<xs:attribute name="RightEyeColor" type="xs:string"
use="optional"/>
<xs:attribute name="LeftEyeColor" type="xs:string"
use="optional"/>
<xs:attribute name="OperatorLicenseNumber" type="xs:string"
use="optional"/>
<xs:attribute name="OperatorLicenseState" type="xs:string"
use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="KnownMatchingPerson" minOccurs="0"
maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="ConfidenceLevel" type="xs:double"
use="required"/>
<xs:attribute name="MPI" type="xs:string" use="required"/>

</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute name="TotalNumberOfMatches" type="xs:integer"
use="required"/>
<xs:attribute name="Timestamp" type="xs:dateTime" use="required"/>

</xs:complexType>

//--------------------------------------------------------------------------
// where ErrorType is
<xs:simpleType name="ErrorType">
<xs:restriction base="xs:string">
<xs:enumeration value="client"/>
<xs:enumeration value="server"/>
</xs:restriction>
</xs:simpleType>



Thanks for your help
Dominique Gaucher
 
S

Steven Cheng[MSFT]

Hi Dominique,

Thanks for your response, as for the .NET wsdl generated proxy class's
return type problem you mentioned, I've done some research on the .NET's
WSDL parser (wsdl.exe) and found that the problem on parsing the
xsd:choice element does be an existing limitation of the .net 's wsdl.exe
tool.

In fact, the xsd:choice type should be mapped to a variant type which can
reference a certain type among a given type groups. However, currently the
..net's wsdl.exe tool dosn't support the correct mapping on such element(
Variant Type). That's why we'll always get the fixed Type object when
consuming a webservivce with a custom WSDL which contains xsd:choice
element as return type.

Currently, the available workaround is to consuming the xmlwebservice
direct via the HttpWebRequest class in the System.Net namespace. The
wsdl.exe generated proxy class is also using the HttpWebRequest to send the
underlying SOAP message internally. So we can create our own custom proxy
class which directly use the HttpWebRequest to send the SOAP xml message
and get the returned XML SOAP message and then parsing the certain object
instance to the correct type (manually use the xmlSerialier).

If there is any further questions, please feel free to post here.
Thanks.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top