By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,473 Members | 3,505 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,473 IT Pros & Developers. It's quick & easy.

Polymorphic return values

P: n/a
I am trying to return one of two different objects from the same
method, but I can not do it in WSDL or C#.

I have a web service with three methods.

I have been told that one of the methods must return either <Respuesta
....> or <ConfirmacionPeticion ...> directly under the SOAP Body. Other
methods are already capable of returning just <Respuesta ...> or just
<ConfirmacionPeticion ...>. What is new is one method being capable of
returning both types.

I have been modifying over one of the previous methods:

[WebMethodAttribute( Description = "Blah...")]
[SoapDocumentMethod( ourMethodNamespace, Use = SoapBindingUse.Literal,
ParameterStyle = SoapParameterStyle.Bare)]
[return: XmlElement( Respuesta.Marca, Namespace =
Respuesta.EspacioNombres)]
public Respuesta solicitaRespuestaAsincrona( ...)

The obvious thing is to substitute the return type by object:

[WebMethodAttribute( Description = "Blah...")]
[SoapDocumentMethod( ourMethodNamespace, Use = SoapBindingUse.Literal,
ParameterStyle = SoapParameterStyle.Bare)]
public object solicitaRespuestaAsincrona( ...)

But then the automatic WSDL becomes:

<wsdl:message name="solicitaRespuestaAsincronaSoapOut">
<wsdl:part name="solicitaRespuestaAsincronaResult"
element="tns:solicitaRespuestaAsincronaResult"/>
</wsdl:message>

That is, under <soap:Body> I get a <solicitaRespuestaAsincronaResult>
element followed by the members of the actual object being returned.
This is not what I want, I want either <Respuesta> or
<ConfirmacionRespuesta>.

I then tried to have several XML return attributes:

[WebMethodAttribute( Description = "Blah...")]
[SoapDocumentMethod( ourMethodNamespace, Use = SoapBindingUse.Literal,
ParameterStyle = SoapParameterStyle.Bare)
[return:
XmlElement( Respuesta.Marca,
Namespace = Respuesta.EspacioNombres),
XmlElement( ConfirmacionPeticion.Marca,
Namespace = ConfirmacionPeticion.EspacioNombres)]]
public object solicitaRespuestaAsincrona( ...)

but then I get:

System.InvalidOperationException: You need to add
XmlChoiceIdentifierAttribute to the 'solicitaRespuestaAsincronaResult'
member.
I then tried the inverse route of hacking the WSDL. I created a new
type:

<wsdl:types>
....
<!-- Since this does not have a namespace, this breaks the Basic
Profile. -->
<s:schema elementFormDefault="qualified">
<s:complexType name="RespuestaOConfirmacion" >
<s:sequence>
<s:choice minOccurs="0" maxOccurs="1">
<s:element minOccurs="1" maxOccurs="1" name="Respuesta" />
<s:element minOccurs="1" maxOccurs="1"
name="ConfirmacionPeticion" />
</s:choice>
</s:sequence>
</s:complexType>
<!-- Without an explicit element:
// CODEGEN: The operation binding 'solicitaRespuestaAsincrona'
from
namespace 'http://www.map.es/scsp/' was ignored.
Specifying a type for use=literal messages is not supported.
Type name='RespuestaOConfirmacion' from targetNamespace=''
cannot be used as top-level any element.-->
<s:element name="RespuestaOConfirmacion"
type="RespuestaOConfirmacion"/>
</s:schema>
</wsdl:types>

and

<wsdl:message name="solicitaRespuestaAsincronaSoapOut">
<wsdl:part name="solicitaRespuestaAsincronaResult"
element="RespuestaOConfirmacion"/>
</wsdl:message>

This type is stubbed as

public partial class RespuestaOConfirmacion
{
[XmlElement("ConfirmacionPeticion", typeof(ConfirmacionPeticion))]
[XmlElement("Respuesta", typeof(Respuesta))]
[XmlChoiceIdentifier("nombreElemento")]
public object unaRespuestaOUnaConfirmacion;

[System.Xml.Serialization.XmlIgnoreAttribute()]
public RespuestaOConfirmacionEleccion nombreElemento;
}

[System.Xml.Serialization.XmlTypeAttribute(IncludeI nSchema =
false)]
public enum
RespuestaOConfirmacionEleccion
{
ConfirmacionPeticion,
Respuesta
}
I then tried with:

....
[return:
XmlChoiceIdentifier(MemberName = "nombreElemento"),
XmlElement( Respuesta.Marca,
Namespace = Respuesta.EspacioNombres),
XmlElement( ConfirmacionPeticion.Marca,
Namespace = ConfirmacionPeticion.EspacioNombres)]
public RespuestaOConfirmacion solicitaRespuestaAsincrona( ...)

This causes:

System.InvalidOperationException: There was an error reflecting
'solicitaRespuestaAsincronaResult'. --->
System.InvalidOperationException: Missing 'nombreElemento' member
needed for serialization of choice 'solicitaRespuestaAsincronaResult'.

in spite of me assigning a value to the nombreElemento field in the
return value.

If I have

[return:
XmlChoiceIdentifier(MemberName = "nombreElemento"),
XmlElement( Respuesta.Marca,
Namespace = Respuesta.EspacioNombres),
XmlElement( ConfirmacionPeticion.Marca,
Namespace = ConfirmacionPeticion.EspacioNombres)]
[return: XmlElement("RespuestaOConfirmacion", Namespace = "")]

the return value is serialized as
<RespuestaOConfirmacion>
<Respuesta ...>
....
</RespuestaOConfirmacion>

That is, the Respuesta or the ConfrimacionPeticion are wrapped with
<RespuestaOConfirmacion> which again is not what I want.
So summarizing, how do you express either in C# or in WSDL that you can
return any of two different elements under <soap:Body>?

Thanks in advance.
--
David Mediavilla

Jan 23 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
My advice u to use a union for multiple return types...

--
HTH

Thanks,
Yunus Emre ALP÷ZEN
BSc, MCSD.NET
Microsoft .NET & Security MVP

<6k*******@sneakemail.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
I am trying to return one of two different objects from the same
method, but I can not do it in WSDL or C#.

I have a web service with three methods.

I have been told that one of the methods must return either <Respuesta
...> or <ConfirmacionPeticion ...> directly under the SOAP Body. Other
methods are already capable of returning just <Respuesta ...> or just
<ConfirmacionPeticion ...>. What is new is one method being capable of
returning both types.

I have been modifying over one of the previous methods:

[WebMethodAttribute( Description = "Blah...")]
[SoapDocumentMethod( ourMethodNamespace, Use = SoapBindingUse.Literal,
ParameterStyle = SoapParameterStyle.Bare)]
[return: XmlElement( Respuesta.Marca, Namespace =
Respuesta.EspacioNombres)]
public Respuesta solicitaRespuestaAsincrona( ...)

The obvious thing is to substitute the return type by object:

[WebMethodAttribute( Description = "Blah...")]
[SoapDocumentMethod( ourMethodNamespace, Use = SoapBindingUse.Literal,
ParameterStyle = SoapParameterStyle.Bare)]
public object solicitaRespuestaAsincrona( ...)

But then the automatic WSDL becomes:

<wsdl:message name="solicitaRespuestaAsincronaSoapOut">
<wsdl:part name="solicitaRespuestaAsincronaResult"
element="tns:solicitaRespuestaAsincronaResult"/>
</wsdl:message>

That is, under <soap:Body> I get a <solicitaRespuestaAsincronaResult>
element followed by the members of the actual object being returned.
This is not what I want, I want either <Respuesta> or
<ConfirmacionRespuesta>.

I then tried to have several XML return attributes:

[WebMethodAttribute( Description = "Blah...")]
[SoapDocumentMethod( ourMethodNamespace, Use = SoapBindingUse.Literal,
ParameterStyle = SoapParameterStyle.Bare)
[return:
XmlElement( Respuesta.Marca,
Namespace = Respuesta.EspacioNombres),
XmlElement( ConfirmacionPeticion.Marca,
Namespace = ConfirmacionPeticion.EspacioNombres)]]
public object solicitaRespuestaAsincrona( ...)

but then I get:

System.InvalidOperationException: You need to add
XmlChoiceIdentifierAttribute to the 'solicitaRespuestaAsincronaResult'
member.
I then tried the inverse route of hacking the WSDL. I created a new
type:

<wsdl:types>
...
<!-- Since this does not have a namespace, this breaks the Basic
Profile. -->
<s:schema elementFormDefault="qualified">
<s:complexType name="RespuestaOConfirmacion" >
<s:sequence>
<s:choice minOccurs="0" maxOccurs="1">
<s:element minOccurs="1" maxOccurs="1" name="Respuesta" />
<s:element minOccurs="1" maxOccurs="1"
name="ConfirmacionPeticion" />
</s:choice>
</s:sequence>
</s:complexType>
<!-- Without an explicit element:
// CODEGEN: The operation binding 'solicitaRespuestaAsincrona'
from
namespace 'http://www.map.es/scsp/' was ignored.
Specifying a type for use=literal messages is not supported.
Type name='RespuestaOConfirmacion' from targetNamespace=''
cannot be used as top-level any element.-->
<s:element name="RespuestaOConfirmacion"
type="RespuestaOConfirmacion"/>
</s:schema>
</wsdl:types>

and

<wsdl:message name="solicitaRespuestaAsincronaSoapOut">
<wsdl:part name="solicitaRespuestaAsincronaResult"
element="RespuestaOConfirmacion"/>
</wsdl:message>

This type is stubbed as

public partial class RespuestaOConfirmacion
{
[XmlElement("ConfirmacionPeticion", typeof(ConfirmacionPeticion))]
[XmlElement("Respuesta", typeof(Respuesta))]
[XmlChoiceIdentifier("nombreElemento")]
public object unaRespuestaOUnaConfirmacion;

[System.Xml.Serialization.XmlIgnoreAttribute()]
public RespuestaOConfirmacionEleccion nombreElemento;
}

[System.Xml.Serialization.XmlTypeAttribute(IncludeI nSchema =
false)]
public enum
RespuestaOConfirmacionEleccion
{
ConfirmacionPeticion,
Respuesta
}
I then tried with:

...
[return:
XmlChoiceIdentifier(MemberName = "nombreElemento"),
XmlElement( Respuesta.Marca,
Namespace = Respuesta.EspacioNombres),
XmlElement( ConfirmacionPeticion.Marca,
Namespace = ConfirmacionPeticion.EspacioNombres)]
public RespuestaOConfirmacion solicitaRespuestaAsincrona( ...)

This causes:

System.InvalidOperationException: There was an error reflecting
'solicitaRespuestaAsincronaResult'. --->
System.InvalidOperationException: Missing 'nombreElemento' member
needed for serialization of choice 'solicitaRespuestaAsincronaResult'.

in spite of me assigning a value to the nombreElemento field in the
return value.

If I have

[return:
XmlChoiceIdentifier(MemberName = "nombreElemento"),
XmlElement( Respuesta.Marca,
Namespace = Respuesta.EspacioNombres),
XmlElement( ConfirmacionPeticion.Marca,
Namespace = ConfirmacionPeticion.EspacioNombres)]
[return: XmlElement("RespuestaOConfirmacion", Namespace = "")]

the return value is serialized as
<RespuestaOConfirmacion>
<Respuesta ...>
...
</RespuestaOConfirmacion>

That is, the Respuesta or the ConfrimacionPeticion are wrapped with
<RespuestaOConfirmacion> which again is not what I want.
So summarizing, how do you express either in C# or in WSDL that you can
return any of two different elements under <soap:Body>?

Thanks in advance.
--
David Mediavilla

Jan 23 '06 #2

P: n/a
Yunus Emre ALP÷ZEN [MVP] wrote:
My advice u to use a union for multiple return types...
I appreciate your answer. From my understanding and the message from
the WSDL editor in Visual Studio, union only works with simpleType.
Respuesta and ConfirmacionPeticion are complexType.

I am going to look into abstract types, but I understand that it
requires including an xsi:type in <Respuesta ...> and
<ConfirmacionPeticion ...>
Yunus Emre ALP÷ZEN

<6k*******@sneakemail.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
I am trying to return one of two different objects from the same
method, but I can not do it in WSDL or C#.

I have a web service with three methods.

I have been told that one of the methods must return either <Respuesta
...> or <ConfirmacionPeticion ...> directly under the SOAP Body. Other
methods are already capable of returning just <Respuesta ...> or just
<ConfirmacionPeticion ...>. What is new is one method being capable of
returning both types. So summarizing, how do you express either in C# or in WSDL that you can
return any of two different elements under <soap:Body>?

Thanks in advance.
--
David Mediavilla


--
David Mediavilla

Jan 24 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.