2009-05-18 6 views
4

J'ai un service WCF qui accepte une chaîne comme paramètre pour l'un de ses contrats d'exploitation. Cette chaîne a cependant un contenu xml.Sérialiser et désérialiser un XmlDocument dans WCF à l'aide de DataContractSerializer

Je dois convertir ceci en une classe marquée DataContract mais qui n'est pas exposée au monde extérieur.

Je dois utiliser le DataContractSerializer car les membres de classe ont l'attribut [DataMember] défini sur un nom différent. Ex: la propriété Phone a le nom DataMember défini comme "Telephone", donc quand je désérialise le xmldocument en utilisant le sérialiseur normal, j'obtiens une erreur car le désérialiseur cherche l'élément Phone qui n'existe pas.

Comment désérialiser un XmlDocument en utilisant le DataContractSerializer? Une contrainte cependant est que je ne peux pas enregistrer le xmldocument dans un fichier.

EDIT: Trouvé un excellent article sur la sérialisation et désérialisation utilisant DataContractSerializer here.

Mon code client:

string xmldata = "<Customer> + 
       System.Environment.NewLine+ 
       "<Age>1</Age>"+ 
       System.Environment.NewLine+ 
       "<BirthDate>1900-01-01T01:01:01.0000000-05:00</BirthDate>" + 
       System.Environment.NewLine+ 
       "<FistName>John</FistName>"+ 
       System.Environment.NewLine + 
       "<LastName>Doe</LastName>" + 
       System.Environment.NewLine + 
       "</Customer>"; 

doc.LoadXml(xmldata); 
Service1Client a = new Service1Client(); 
a.GetData(doc.OuterXml.ToString()); 

Mon code de service:

public string GetData(string per) 
{ 
    string xmldata = per; 
    XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.LoadXml(xmldata); 
    XmlDemo.Person a = Person.Create(); 

    DataContractSerializer ser = new DataContractSerializer(a.GetType()); 
    StringWriter stringWriter = new StringWriter(); 
    XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter); 
    xmlDoc.WriteTo(xmlWriter); 

    MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(stringWriter.ToString())); 
    stream.Position = 0; 
    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()); 
    Person myContact = (Person)ser.ReadObject(reader, true); 

    return string.Empty; 

} 

Mon DataContract:

[Serializable] 
[DataContract(Name = "Customer")] 
public class Person 
{ 
    private Person() {} 
    [DataMember(Name = "FistName")] 
    public string FName { get; set; } 
    [DataMember(Name = "LastName")] 
    public string LName { get; set; } 
    [DataMember(Name = "Age")] 
    public int Age { get; set; } 
    [DataMember(Name = "BirthDate")] 
    public DateTime DOB { get; set; } 

    public static Person Create() 
    { 
     return new Person(); 
    } 
} 

J'ai cette erreur chez Person myContact = (Person) ser.ReadObject (reader, true);

 
Error in line 1 position 11. Expecting element 'Customer' from namespace 'http://schemas.datacontract.org/2004/07/XmlDemo'.. Encountered 'Element' with name 'Customer', namespace ''. 
+0

Pourriez-vous reformuler la question et être un peu plus précis? Je ne comprends pas ce que vous voulez – alanquillin

+0

@aquillin - Je l'ai reformulé – Developer

Répondre

2

Deserialize de droit chemin chaîne

MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes("<myXml />")); 
stream.Position = 0; 
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()); 
MyContact myContact = (MyContact)ser.ReadObject(reader, true); 

Deserialize de XmlDocument

StringWriter stringWriter = new StringWriter(); 
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter); 
xmlDoc.WriteTo(xmlWriter); 

MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(stringWriter.ToString())); 
stream.Position = 0; 
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()); 
MyContact myContact = (MyContact)ser.ReadObject(reader, true); 
+0

J'ai essayé votre approche, j'ai énuméré mon code complet et le message d'erreur que je reçois quand je l'essaie avec votre code. – Developer

+0

évidemment, vous avez déclaré l'espace de noms http://schemas.datacontract.org/2004/07/XmlDemo quelque part dans votre service WCF, dans ce cas, vous devez prendre soin de l'espace de noms pour le désérialiseur. –

+0

Merci! J'ai mis [Namespace = ""] pour le contrat de données et cela fonctionne maintenant. – Developer

1

Est-ce votre service? Si tel est le cas, n'envoyez ni ne recevez pas de code XML dans un paramètre string, car ce n'est pas la même chose. De plus, bien que vous n'ayez pas exposé le DataContract dans lequel vous souhaitez désérialiser ce XML dans le monde, vous l'avez pratiquement fait en exposant le code XML. C'est en grande partie le même effet. Vous devriez donc créer une classe DataContract qui n'a aucun comportement associé, puis l'exposer dans votre contrat de service. Si vous avez besoin de l'utiliser en interne en tant que données dans une classe avec un comportement, copiez les données dans une nouvelle instance de votre classe interne, que vous n'exposez jamais. Je recommande toujours que vous arrêtiez cette sottise en copiant XML dans et hors des chaînes. Pourtant, d'après le code et l'exception que vous avez affichée:

Pourquoi cette

XmlDemo.Person a = Person.Create(); 

puis essuyez-le quand vous désérialiser?

XmlDemo.Personne a;

est adéquat. Ensuite, utilisez typeof (XmlDemo.Person) au lieu de a.GetType().

De même, la classe Person que vous avez publiée correspond-elle à la même classe "XmlDemo.Person"? Je suis très curieux de savoir d'où vient cet espace de noms. Pour supprimer mon incertitude, essayez de modifier l'attribut [DataContract] pour dire Namespace = String.Empty (ou peut-être Namespace = null).

Enfin, avez-vous déjà entendu celui sur le développeur qui n'a pas appelé Dispose sur les instances de classes qui implémentent IDisposable?

+0

Le code que j'ai posté est un méli-mélo de choses différentes que j'essayais de faire. La méthode d'usine n'appartient pas ici. Je suppose que j'aurais dû nettoyer le code avant de le poster :) Je suis d'accord avec ne pas passer xml comme chaîne, mais ce design a été transmis par le "architecte" de l'application ... – Developer

+0

Merci John, vous aviez raison à propos de l'espace de noms, malheureusement, SO ne me permet pas de marquer plusieurs réponses comme des réponses. – Developer

Questions connexes