Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / ASP.NET / Web Services / January 2006

Tip: Looking for answers? Try searching our database.

Polymorphic return values

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
6kjfsyg02@sneakemail.com - 23 Jan 2006 17:02 GMT
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(IncludeInSchema =
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
Yunus Emre ALPÖZEN [MVP] - 23 Jan 2006 20:04 GMT
My advice u to use a union for multiple return types...

Signature

HTH

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

>I am trying to return one of two different objects from the same
> method, but I can not do it in WSDL or C#.
[quoted text clipped - 157 lines]
> --
> David Mediavilla
6kjfsyg02@sneakemail.com - 24 Jan 2006 12:13 GMT
> 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
>
[quoted text clipped - 8 lines]
> > <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

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.