Polymorphic return values

Discussion in 'ASP .Net Web Services' started by 6kjfsyg02@sneakemail.com, Jan 23, 2006.

  1. Guest

    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
    , Jan 23, 2006
    #1
    1. Advertising

  2. My advice u to use a union for multiple return types...

    --
    HTH

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

    <> wrote in message
    news:...
    >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], Jan 23, 2006
    #2
    1. Advertising

  3. Guest

    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
    >
    > <> wrote in message
    > news:...
    > >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, 2006
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Manco

    can webmethods be polymorphic?

    Manco, Feb 3, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    314
    Lionel LASKE
    Feb 3, 2005
  2. Thomas Britton

    polymorphic behaviour from class constant

    Thomas Britton, May 1, 2004, in forum: Java
    Replies:
    1
    Views:
    325
    Chris Uppal
    May 2, 2004
  3. Aryeh M. Friedman
    Replies:
    2
    Views:
    1,088
    Ron Natalie
    Feb 21, 2005
  4. Greenhorn
    Replies:
    15
    Views:
    793
    Keith Thompson
    Mar 6, 2005
  5. Chris Rebert
    Replies:
    1
    Views:
    671
    Bobby
    May 28, 2009
Loading...

Share This Page