miércoles, 25 de septiembre de 2013

Data Contract Serializer y maxOccurs="unbounded"

Hace unos días tuve un problema al actualizar un "Service Reference" a partir de un wsdl contra el que ya estábamos trabajando en producción pero necesitábamos ampliar algunas funcionalidades. El problema surgió al actualizar desde Visual Studio el proxy. En un principio no devolvió ningún error ni warning pero dejó de compilar el proyecto y empezó a fallar por todos lados... a priori el wsdl sólo se había modificado para añadir un nuevo método.

El error de compilación surge porque en el proxy (generado automáticamente) todas los objetos List<> han pasado a convertirse en array[], además se han añadido unos atributos

Specified

de tipo bool por cada propiedad pública que si no se les da valor true los datos no llegaban a servidor...

Tirando del hilo, veo que las clases se han generado a partir de XmlSerializer cuando hasta ahora estaba usando

Data Contract Serializer

que es serializador por defecto si usamos Service Reference de Visual Studio... Comparando directamente las diferencias entre los archivos del

wsdl

-

xsd

vimos que se había añadido una lista de string con el atributo

maxOccurs=unbounded

y que este atributo no es compatible con

Data Contract Serializer

tal y como estaba especificado en el fichero.

Soluciones:
  • La más sencilla y de estar por casa es eliminar el atributo manualmente del xsd, con esto ya funcionaría y podríamos salir del apuro.
  • La otra es ajustar el

    xsd

    como se explica a continuación para que

    Data Contract Serializer

    no de problemas

Fragmento xsd que da problemas con

Data Contract Serializer

:
<xs:complexType name="Response">
  <xs:sequence>
    <xs:element name="error" type="xs:boolean" />
    <xs:element name="errorMessage" nillable="true" type="xs:string" />
    <xs:element minOccurs="0" maxOccurs="unbounded" name="info" type="xs:string" />
  </xs:sequence>
</xs:complexType>
Fragmento xsd correcto:
<xs:complexType name="Response">
   <xs:sequence>
      <xs:element name="error" type="xs:boolean" />
      <xs:element name="errorMessage" nillable="true" type="xs:string" />
      <xs:element minOccurs="0" name="mensajes" nillable="true" type="tns:ArrayOfInfo" />
    </xs:sequence>
</xs:complexType>

<xs:complexType name="ArrayOfInfo">
   <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="info" nillable="true" type="xs:string" />
   </xs:sequence>
</xs:complexType>
Una vez optamos por una de estas 2 soluciones al actualizar servicio desde Visual Studio ya usa

Data Contract Serializer

de modo que nos hemos evitado tener que hacer refactoring de código y podemos seguir usando List<> que siempre es más cómodo que un array[].

Hasta aquí el artículo, espero que a alguien le sea útil. Recordar que podéis seguir

areaTIC

en las principales redes sociales, animaros a participar!

No hay comentarios:

Publicar un comentario