2013-03-06 8 views
25

Sto serializzando i dati in un Mono Per l'applicazione Android e inviandolo tramite REST a un server .NET che ascolta usando WCF. Finora questo ha funzionato bene, tuttavia, con questo particolare contratto di dati, anche se il server non lancia errori, gli elenchi all'interno del contratto dati appaiono vuoti.L'output di DataContractSerializer varia tra .NET e Mono

Utilizzando Fiddler e creando due progetti con lo stesso codice, sono riuscito a confrontare il normale output .NET DataContractSerializer con l'output dell'implementazione di DataContractSerializer di Mono.

uscita 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> 

Mono Uscita:

<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> 

Ottimizzare il XML utilizzando Fiddler e le osservazioni di test, ho ristretto il problema per i nomi degli elementi sotto _list elementi:

.NET:

<d2p1:_list> 
     <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU> 

Mono:

<d2p1:_list> 
     <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx> 

Questo è il mio codice che serializza i dati:

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); 
} 

È questo un bug che deve essere affrontato dal Mono team o qualcuno può suggerire una possibile soluzione alternativa?

Edit:

Sono stato restringimento questo problema ulteriormente verso il basso e non si tratta di liste, si tratta del modo in cui ogni applicazione sceglie nomi degli elementi XML.

IdentityDataReference accetta un tipo generico e in questo caso è di tipo CheckListAnswerDataContractEx.

IdentityDataReference si trova anche in una DLL distribuita (di cui ho il codice sorgente), quindi il mio sospetto è che DataContractSerializer stia utilizzando la reflection per calcolare automaticamente il nome e forse dato che è una DLL distribuita separatamente, .NET sta aggiungendo X8I0_S_SPU alla fine, tuttavia, Mono non lo è.

Ho anche scoperto che posso aggiungere un nome paramater al DataContractAttribute in questo modo: [DataContract(Name = "IdentityDataReference")], che avrà la precedenza il nome generato per essere solo IdentityDataReference, non ha nemmeno provare ad aggiungere il tipo di quando specificato.

Sfortunatamente un rapido test mostra che Mono subisce un'eccezione di runtime quando si specifica il nome e si tenta di deserializzare i dati.

Ora che ho capito meglio il problema, sto cercando di realizzare un progetto isolato che replichi il problema.

Edit - Marcatura come deliberato:

sono passato da questo progetto molti anni fa, ma ha deciso di chiudere questo come risposta da Katulus poiché mi sentirei incontrando lo stesso oggi lo stesso problema. Speravamo che al momento potessimo ottenere un'integrazione inter-piattaforma "gratuita" indolore, senza lavoro aggiuntivo per un servizio WCF esistente, che si è rivelato ingenuo.

Oggi se presentato lo stesso requisito, preferirei invece un protocollo di comunicazione più multipiattaforma. Se non potessi sostituire l'infrastruttura WCF esistente, creerei una sorta di facade e/o adapter (possibilmente in una soluzione diversa) che espone il servizio su qualcosa come WebAPI usando la serializzazione JSON, parlando al servizio WCF originale nel sfondo.

+5

Se si scopre che si tratta di un bug, è possibile segnalarlo a Xamarin all'indirizzo https://bugzilla.xamarin.com/. – Dandy

+3

Abbiamo visto lo stesso problema. Xamarin non aggiunge un hash al nome del contratto dati per tipi generici, come fa .NET. La soluzione alternativa era utilizzare DataContractResolver, poiché supportiamo più piattaforme e non è stato possibile modificare il nome, ad es. '[DataContract (Name =" IdentityDataReferenceOf {0} ")]' in essi a causa della possibilità di conflitti di nomi. –

+0

Perché dovresti compilare un'applicazione di servizio usando mono? Immagino che tu l'abbia fatto. – danish

risposta

3

Se si sta comunicando tra diverse piattaforme (anche se .NET e Mono cercare di essere lo stesso), si dovrebbe evitare di utilizzare DataContractSerializer. Ci sono altri problemi possibili oltre a questo bug. Se ad esempio si cambiano le classi sul server, tutti i client potrebbero smettere di funzionare e viceversa. Nello scenario server-client in cui non si ha il pieno controllo di entrambe le parti, questo può essere un grosso problema.

Vorrei modificare DataContractSerializer in XmlSerializer che è possibile controllare meglio su entrambi i lati. O addirittura implementare la propria serializzazione da e verso XML in cui è possibile tenere conto degli aggiornamenti futuri. Se si aggiunge una nuova proprietà su un server, è possibile aggiornare il deserializzatore in modo che possa gestire se tale nuova proprietà manca a un vecchio client.

+0

Pertanto implementiamo sempre la rigenerazione degli oggetti di trasferimento dati (DTO) automaticamente durante la costruzione notturna. Il servizio esporta i contratti che i client utilizzano per rigenerare i propri proxy e sia il servizio che il client generano i DTO dallo stesso XSD. Quello che chiamiamo Contract First Development. – riezebosch

0

Forse una soluzione alternativa è utilizzare l'applicazione svcutil per generare il proxy e quindi utilizzare lo stesso proxy così com'è. http://tutorials.csharp-online.net/WCF_Essentials%E2%80%94Generating_the_Proxy

In generale penso che si dovrebbe iniziare a utilizzare lo spazio dei nomi del DataContract, in quanto mi ha aiutato più volte l'identificazione dei problemi di versione di riferimento è solo in modo molto bello avere quale versione del codice è in esecuzione con proxy per. Ma questa è un'altra commissione :)

Forse quando si effettua il riferimento, se è possibile aggiungere un riferimento a una libreria pubblica contenente l'interfaccia, è possibile utilizzare i tipi di riutilizzo delle impostazioni di riferimento del servizio da assembly referenziati che quindi non verranno resi disponibili rendere i propri tipi alla stessa estensione.

Infine c'è, visualizza tutti i file Reference.svcmap sotto un riferimento di servizio, questo xml contiene un elemento 'CollectionMappings', che spesso è stato necessario specificare per il mio elenco di comportarsi nel qual caso questo articolo fornisce alcune informazioni :
http://social.msdn.microsoft.com/Forums/vstudio/en-US/09eefbbc-bf63-4aa3-a0cb-01a9dbd7f496/problem-sharing-custom-collection-types-between-service-and-client

Ecco i miei cinque centesimi di suggerimenti di debug,
acclamazioni