Salida de DataContractSerializer difiere between.NET y Mono


Estoy serializando datos en una aplicación Mono para Android y enviándolos usando REST a un servidor.NET escuchando usando WCF. Hasta ahora esto ha funcionado bien, sin embargo, con este contrato de datos en particular, aunque el servidor no arroja errores, las Listas dentro del contrato de datos aparecen como vacías.

Usando Fiddler y creando dos proyectos con el mismo código, pude comparar la salida normal de. NET DataContractSerializer con la salida de la implementación de Mono de DataContractSerializer.

Salida. NET:

<VisitDataContractEx xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts">
  <_isDirty xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">true</_isDirty>
  <_id xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.Domain" xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:internalValue>a7b97b48-d3a9-419d-9f4e-330ffc7a01ee</d2p1:internalValue>
  </_id>
  <_key xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">false</_key>
  <_keyIdentifier xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">SurrogateKey</_keyIdentifier>
  <ChecklistComplete>false</ChecklistComplete>
  <Date>2013-03-05T15:43:49.5008406+02:00</Date>
  <GpsAccuracy>1</GpsAccuracy>
  <GpsLatitude>1</GpsLatitude>
  <GpsLongitude>1</GpsLongitude>
  <OrderComplete>false</OrderComplete>
  <PhotoComplete>false</PhotoComplete>
  <StockComplete>false</StockComplete>
  <Sync>2013-03-05T15:43:49.5468406+02:00</Sync>
  <checkListAnswers xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU>
        <d2p1:_dataContract z:Id="i2">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>95ae919b-a389-4ea7-a009-af1b91890c36</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Answer>false</Answer>
          <checkListQuestion>
            <d2p1:_dataContract i:nil="true" />
            <d2p1:_description i:nil="true" />
            <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
            <d2p1:_id xmlns:d7p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
              <d7p1:internalValue>176cbb31-7df2-4966-baa9-4e3cd2a0c6d5</d7p1:internalValue>
            </d2p1:_id>
          </checkListQuestion>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>95ae919b-a389-4ea7-a009-af1b91890c36</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU>
    </d2p1:_list>
  </checkListAnswers>
  <comments xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list />
  </comments>
  <directSalesAgent xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>6f99f86a-5b1b-4f73-bdc3-388e0b7cf417</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgent>
  <directSalesAgentSuperVisor xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>d57db20d-9b3a-4345-849e-d5a0d0d88f70</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgentSuperVisor>
  <photos xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfPhotoDataContractExX8I0_S_SPU>
        <d2p1:_dataContract z:Id="i3">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>3db431e9-3338-4c96-aea9-d833eb0dc8ae</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Content i:nil="true" />
          <Taken>2013-03-05T15:43:49.4748406+02:00</Taken>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>3db431e9-3338-4c96-aea9-d833eb0dc8ae</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfPhotoDataContractExX8I0_S_SPU>
    </d2p1:_list>
  </photos>
  <salesPoint xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>692a294a-2d1b-4026-9693-0c0ce552a2fb</d3p1:internalValue>
    </d2p1:_id>
  </salesPoint>
  <stockCounts xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts" i:nil="true" />
</VisitDataContractEx>

Salida mono:

<VisitDataContractEx xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts">
  <_isDirty xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">true</_isDirty>
  <_id xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.Domain" xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:internalValue>9297eea9-82af-4981-ab9d-40aa0ac0fa0d</d2p1:internalValue>
  </_id>
  <_key xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">false</_key>
  <_keyIdentifier xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">SurrogateKey</_keyIdentifier>
  <ChecklistComplete>false</ChecklistComplete>
  <Date>2013-03-05T17:49:06.362243+02:00</Date>
  <GpsAccuracy>1</GpsAccuracy>
  <GpsLatitude>1</GpsLatitude>
  <GpsLongitude>1</GpsLongitude>
  <OrderComplete>false</OrderComplete>
  <PhotoComplete>false</PhotoComplete>
  <StockComplete>false</StockComplete>
  <Sync>2013-03-05T17:49:06.438934+02:00</Sync>
  <checkListAnswers xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx>
        <d2p1:_dataContract xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" z:Id="i2">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>75083457-9714-4971-b60c-f28fa43167ad</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Answer>false</Answer>
          <checkListQuestion xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
            <d6p1:_dataContract xmlns:d7p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
            <d6p1:_description i:nil="true" />
            <d6p1:_hasDataContract>false</d6p1:_hasDataContract>
            <d6p1:_id xmlns:d7p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
              <d7p1:internalValue>176cbb31-7df2-4966-baa9-4e3cd2a0c6d5</d7p1:internalValue>
            </d6p1:_id>
          </checkListQuestion>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>75083457-9714-4971-b60c-f28fa43167ad</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx>
    </d2p1:_list>
  </checkListAnswers>
  <comments xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list />
  </comments>
  <directSalesAgent xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>6f99f86a-5b1b-4f73-bdc3-388e0b7cf417</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgent>
  <directSalesAgentSuperVisor xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>d57db20d-9b3a-4345-849e-d5a0d0d88f70</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgentSuperVisor>
  <photos xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfPhotoDataContractEx>
        <d2p1:_dataContract xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" z:Id="i3">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>507f45d1-ce3a-4ec2-a343-d0b83cfb7bc8</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Content i:nil="true" />
          <Taken>2013-03-05T17:49:06.294006+02:00</Taken>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>507f45d1-ce3a-4ec2-a343-d0b83cfb7bc8</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfPhotoDataContractEx>
    </d2p1:_list>
  </photos>
  <salesPoint xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>692a294a-2d1b-4026-9693-0c0ce552a2fb</d3p1:internalValue>
    </d2p1:_id>
  </salesPoint>
  <stockCounts xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts" i:nil="true" />
</VisitDataContractEx>

Ajustando el XML usando Fiddler y testing submissions, he reducido el problema a los nombres de elementos bajo _list elements:

. NET:

    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU>

Mono:

    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx>

Este es mi código que serializa los datos: {[13]]}

public string Serialize<TDataContract>(object obj)
{
    var builder = new StringBuilder();
    var serializer = new DataContractSerializer(typeof(TDataContract));
    var xmlWriter = XmlWriter.Create(builder);
    serializer.WriteObject(xmlWriter, obj);
    xmlWriter.Close();

    return builder.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", string.Empty);
}

¿Es este un error que tiene que ser abordado por el equipo Mono, o puede alguien sugerir un posible solución?

Editar:

He estado reduciendo este problema aún más y no se trata de listas, se trata de la forma en que cada implementación elige los nombres de los elementos XML.

IdentityDataReference toma un tipo genérico, y en este caso es de tipo CheckListAnswerDataContractEx.

IdentityDataReference también pasa a estar en una DLL distribuida (que tengo el código fuente para), por lo que mi sospecha es que DataContractSerializer está utilizando reflexión para trabajar el nombre automáticamente, y tal vez como es una DLL distribuida por separado,. NET está anexando X8I0_S_SPU al final, sin embargo, Mono no lo es.

También he descubierto que puedo agregar un parámetro de nombre al DataContractAttribute de la siguiente manera: [DataContract(Name = "IdentityDataReference")] que anulará el nombre generado para que solo sea IdentityDataReference, ni siquiera intenta agregar el Tipo de cuando se especifica.

Desafortunadamente, una prueba rápida muestra que Mono está sufriendo una excepción de tiempo de ejecución cuando especifico el nombre y trata de deserializar los datos.

Ahora que entiendo la problema mejor, estoy tratando de hacer un proyecto aislado que replica el problema.

Edición-Marcado como resuelto:

Pasé de este proyecto hace muchos años, pero decidí cerrar esto como respondió Katulus ya que me sentiría igual hoy encontrando el mismo problema. Era nuestra esperanza en ese momento que pudiéramos obtener una integración "gratuita" sin dolor entre plataformas sin trabajo adicional para un servicio WCF existente, lo que resultó ser ingenuo.

Hoy si presentado el mismo requisito, en su lugar elegiría un protocolo de comunicación más amigable plataforma cruzada. Si no pudiera reemplazar la infraestructura WCF existente, entonces crearía algún tipo de facade y/o adapter (posiblemente en una solución diferente) que expone el servicio sobre algo como WebAPI usando serialización JSON, hablando con el servicio WCF original en segundo plano.

Author: Jonathan L., 2013-03-06

2 answers

Si se está comunicando entre diferentes plataformas (aunque.NET y Mono intenten ser lo mismo), debe evitar usar DataContractSerializer. Hay otros posibles problemas además de este error. Si, por ejemplo, cambia clases en el servidor, todos los clientes pueden dejar de funcionar y viceversa. En el escenario servidor-cliente donde no tiene el control total de ambos lados, esto puede ser un gran problema.

Cambiaría DataContractSerializer a XmlSerializer que puede controlar mejor en ambos lados. O incluso implementar propia serialización hacia y desde XML donde se puede dar cuenta con futuras actualizaciones. Si agrega alguna propiedad nueva en un servidor, puede actualizar su deserializer de una manera que pueda manejar si esa nueva propiedad falta en algún cliente antiguo.

 3
Author: Katulus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-02 08:42:44

Quizás una solución es usar la aplicación svcutil para generar el proxy y luego usar el mismo proxy que está. http://tutorials.csharp-online.net/WCF_Essentials%E2%80%94Generating_the_Proxy

Generalmente creo que debería comenzar a usar el espacio de nombres del datacontract, ya que me ha ayudado varias veces a identificar problemas de versión de referencia.Es muy bueno tener para qué versión se está ejecutando el código con proxies. Pero eso es otro recado :)

Tal vez al hacer la referencia, si puede agregar una referencia a la biblioteca pública que contiene su interfaz, puede usar la configuración de referencia de servicio 'reutilizar tipos de ensamblados referenciados' que luego hará que no creen tipos propios a la misma extensión.

Finalmente está la Referencia visible, mostrar todos los archivos.svcmap bajo una referencia de servicio, este xml contiene un elemento 'CollectionMappings', que a menudo ha sido necesario especificar para que mi lista se comporte en cuyo caso este artículo da algunos insight:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/09eefbbc-bf63-4aa3-a0cb-01a9dbd7f496/problem-sharing-custom-collection-types-between-service-and-client

Esos son mis cinco centavos de pistas de depuración,
Salud

 0
Author: T. Nielsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-31 10:24:10