none
DataContractJsonSerializer n'arrive pas à remplir mes objets correctement RRS feed

  • Question

  • Bonsoir.

    Je développement actuellement un web service WCf en C# et j'utilise pour communiquer des méthodes envoyant et lisant des flux JSON. La génération des méthodes GET de ce web service ne pose aucun soucis (et elles sont déja implémentées), cependant je rencontre un soucis sur la première méthode POST du web service.

    En effet, cette méthode prend en paramètre un Stream (une JSONStringer envoyé d'une application mobile) et doit pouvoir transformer ce Stream en un objet. Voici l'implémentation actuelle de ceci :

    Déclaration de l'OperationContract

    [OperationContract]
    [WebInvoke
      (Method = "POST",
      UriTemplate = "CreateDelivery",
      BodyStyle = WebMessageBodyStyle.Bare,
      ResponseFormat = WebMessageFormat.Json,
      RequestFormat = WebMessageFormat.Json)]
    String CreateDelivery(Stream Appointment);
    

    Déclaration de la Méthode

    public String CreateDelivery(Stream Appointment)
    {
                if (Appointment != null)
                {
                    StreamReader reader = new StreamReader(Appointment);
                    string res = reader.ReadToEnd();
                    reader.Close();
                    reader.Dispose();
    
                    Appointment deserializedAppointment = new Appointment();
                    MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(res));                
                    
                    DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedAppointment.GetType());
                    deserializedAppointment = (Appointment)ser.ReadObject(ms);
                    ms.Close();
                    ms.Dispose();
    
                    return "Received: " + res + " App ID : " + deserializedAppointment.Id;
    }

    Déclaration de l'objet Appointment

    [DataContract (Name="Appointment")]
        public class Appointment
        {
            private int _id;
            private Customer _customer;
            private int _typeId;
            private Delivery _delivery;
            private DateTime _dateBegin;
            private DateTime _dateEnd;
            private string _comment;
            private int _order;
            private Boolean _callCustomer;
            private Boolean _urgent;
            private string _attachement;
            private int _InterventionId;
    
            [DataMember (Order = 1, Name="idapp")]
            public int Id 
            { 
                get 
                { 
                    return _id; 
                }
                
                set
                {
                    _id = value;
                }
            }
    
            [DataMember(Order = 2, Name = "customer")]
            public Customer CustomerId 
            {
                get
                {
                    return _customer;
                }
    
                set
                {
                    _customer = value;
                }
            }
    
            [DataMember(Order = 3, Name = "idtyp")]
            public int TypeId
            {
                get
                {
                    return _typeId;
                }
    
                set
                {
                    _typeId = value;
                }
            }
    
            [DataMember(Order = 4, Name = "delivery")]
            public Delivery DeliveryId
            {
                get
                {
                    return _delivery;
                }
    
                set
                {
                    _delivery = value;
                }
            }
    
            [DataMember(Order = 5, Name = "datebegin")]
            public DateTime DateBegin
            {
                get
                {
                    return _dateBegin;
                }
    
                set
                {
                    _dateBegin = value;
                }
            }
    
            [DataMember(Order = 6, Name = "dateend")]
            public DateTime DateEnd
            {
                get
                {
                    return _dateEnd;
                }
    
                set
                {
                    _dateEnd = value;
                }
            }
    
            [DataMember(Order = 7, Name = "com")]
            public string Comment
            {
                get
                {
                    return _comment;
                }
    
                set
                {
                    _comment = value;
                }
            }
    
            [DataMember(Order = 8, Name = "order")]
            public int Order
            {
                get
                {
                    return _order;
                }
    
                set
                {
                    _order = value;
                }
            }
    
            [DataMember(Order = 9, Name = "call")]
            public Boolean CallCustomer
            {
                get
                {
                    return _callCustomer;
                }
    
                set
                {
                    _callCustomer = value;
                }
            }
    
            [DataMember(Order = 10, Name = "urg")]
            public Boolean Urgent
            {
                get
                {
                    return _urgent;
                }
    
                set
                {
                    _urgent = value;
                }
            }
    
            [DataMember(Order = 11, Name = "att")]
            public string Attachment
            {
                get
                {
                    return _attachement;
                }
    
                set
                {
                    _attachement = value;
                }
            }
    
            [DataMember(Order = 12, Name = "inter")]
            public int Intervention {
                get
                {
                    return _InterventionId;
                }
                set
                {
                    _InterventionId = value;
                }
            }
    }
    


    Déclaration de l'objet Customer

    [DataContract]
        public class Customer
        {
            private int _id;
            private string _name;
            private string _code;
            private string _deliveryAddress1;
            private string _deliveryAddress2;
            private string _deliveryAddress3;
            private string _zipCode;
            private string _city;
            private string _contact;
            private string _phone;
            private string _mail;
            private string _family;
            private string _risk;
    
            [DataMember(Order = 1, Name = "idcus")]
            public int Id 
            {
                get
                {
                    return _id;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 2, Name = "code")]
            public string Code
            {
                get
                {
                    return _code;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 3, Name = "name")]
            public string Name
            {
                get
                {
                    return _name;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 4, Name = "add1")]
            public string AddressLiv1
            {
                get
                {
                    return _deliveryAddress1;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 5, Name = "add2")]
            public string AddressLiv2
            {
                get
                {
                    return _deliveryAddress2;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 6, Name = "add3")]
            public string AddressLiv3
            {
                get
                {
                    return _deliveryAddress3;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 7, Name = "zip")]
            public string ZipCode
            {
                get
                {
                    return _zipCode;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 8, Name = "city")]
            public string City
            {
                get
                {
                    return _city;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 9, Name = "contact")]
            public string Contact
            {
                get
                {
                    return _contact;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 10, Name = "phone")]
            public string Phone
            {
                get
                {
                    return _phone;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 11, Name = "mail")]
            public string Mail
            {
                get
                {
                    return _mail;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 12, Name = "fam")]
            public string Family
            {
                get
                {
                    return _family;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 13, Name = "risk")]
            public string Risk
            {
                get
                {
                    return _risk;
                }
                set
                {
                }
            }
    }
    


    Déclaration de l'objet Delivery

    [DataContract]
        public class Delivery
        {
            private int _id;
            private string _number;
            private DateTime _dateBegin;
            private DateTime _dateEnd;
            private string _userComment;
            private string _userSignature;
            private string _customerComment;
            private string _customerSignature;
            private string _customerMail;
            private Boolean _commercialAction;
    
            [DataMember(Order = 1, Name = "iddel")]
            public int Id 
            {
                get
                {
                    return _id;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 2, Name = "nb")]
            public string Number
            {
                get
                {
                    return _number;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 3, Name = "datebegin")]
            public DateTime DateBeginDel
            {
                get
                {
                    return _dateBegin;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 4, Name = "dateend")]
            public DateTime DateEndDel
            {
                get
                {
                    return _dateEnd;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 5, Name = "ucom")]
            public string UserComment
            {
                get
                {
                    return _userComment;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 6, Name = "usign")]
            public string UserSignature
            {
                get
                {
                    return _userSignature;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 7, Name = "ccom")]
            public string CustomerComment
            {
                get
                {
                    return _customerComment;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 8, Name = "csign")]
            public string CustomerSignature
            {
                get
                {
                    return _customerSignature;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 9, Name = "cmail")]
            public string CustomerMail
            {
                get
                {
                    return _customerMail;
                }
                set
                {
                }
            }
    
            [DataMember(Order = 10, Name = "cact")]
            public Boolean CommercialAction
            {
                get
                {
                    return _commercialAction;
                }
                set
                {
                }
            }
    }
    

    Et enfin, la String que je récupère bien via la méthode du web service

    {\"Appointment\":{\"Id\":32,\"CustomerId\":{\"Id\":2,\"Code\":\"92320\",\"Name\":\"STOP TELECOM\",\"AddressLiv1\":\"11, rue du Gay Lussac\",\"AddressLiv2\":\"Agence Versailles\",\"AddressLiv3\":\"Agence Brie Comte Robert\",\"ZipCode\":\"92320\",\"City\":\"Châtillon\",\"Contact\":\"Stop Telecom\",\"Phone\":\"01.41.90.71.71\",\"Mail\":\"stop@stop.fr\",\"Family\":\"test\",\"Risk\":\"aucun\"},\"TypeId\":2,\"DeliveryId\":{\"Id\":1,\"Number\":\"92320-111121A\",\"DateBeginDel\":\"24\\\/11\\\/2011 18:53\",\"DateEndDel\":\"24\\\/11\\\/2011 18:53\",\"UserComment\":\"\",\"UserSignature\":\"\",\"CustomerComment\":\"\",\"CustomerSignature\":\"\",\"CustomerMail\":\"stop@stop.fr\",\"CommercialAction\":false},\"DateBegin\":\"2011-11-22 08:00:00\",\"DateEnd\":\"2011-11-22 08:30:00\",\"Comment\":\"\",\"Order\":0,\"CallCustomer\":false,\"Urgent\":false,\"Attachment\":\"\",\"Intervention\":2}}
    

    On peut donc voir que la méthode récupère bien la JSONStringer comme il faut. Malgré cela, le DataContractJsonSerializer n'arrive pas à faire le lien entre les objets présents dans la JSONStringer et les objets du web service.

    Quelqu'un aurait-il une idée sur le pourquoi de ce non fonctionnement ? (j'ai pu le vérifier en voulant afficher l'Id de l'Appointment. Celui m'est toujours renvoyé à 0).

    Par avance, merci de votre retour.

    • Type modifié Ciprian Duduiala jeudi 24 novembre 2011 07:32 thread double http://social.msdn.microsoft.com/Forums/fr-FR/visualcsharpfr/thread/334b1208-1063-4b84-a3c6-30144c188a84
    • Type modifié Ciprian Duduiala jeudi 24 novembre 2011 07:32
    • Type modifié Ciprian Duduiala jeudi 24 novembre 2011 07:33
    mercredi 23 novembre 2011 17:59

Réponses

  • Bonjour Flo,

    Utilisez Fiddler et regardez ce qui se passe dans les requêtes HTTP GET et POST, ça vous aidera à comprendre le problème.

    Pour la sérialisation en JSon. Je vous invite à jeter un coup d’œil à cette documentation.

    Bien cordialement,


    aelassas.free.fr
    mercredi 23 novembre 2011 23:07
    Auteur de réponse
  • Bonjour,

    Je vous invite à jeter un coup d'oeil à ces Webcasts tirés du site officiel de Fiddler sur mon blog.

    Cordialement,


    aelassas.free.fr
    jeudi 24 novembre 2011 13:09
    Auteur de réponse
  • Bonjour,

    Comme je le pensais dans mon message précédent, le désérialiseur rencontrait un soucis au niveau du format des dates passées. Il ne comprend pas le format de date lisible pour un humain, à savoir "25/11/2011 10:25:00". Il faut passer dans les champs DateTime la date au format Timestamp de cette manire : "\/(Date:1322298900000+0000)\/" afin que la Date soit retranscrite dans la propriété correspondante comme il se doit.

    Cependant, je rencontre un nouveau soucis. J'ai deux objets présents dans l'objet Appointment (Customer et Delivery) et ces objets restent à null lors de la désérialisation.
    Manquerait-il un champ dans ma JSONStringer afin d'indiquer au désérialiseur à quels objets correspondent les pairs "key:value" ?

    En tout cas, merci de votre aide, cela m'a permis d'en apprendre plus sur Fiddler et le fonctionnement du DataContractJsonSerializer.
    Cordialement.

    Edit : mon problème est résolu et le DataContractJsonSerializer fonctionne correctement maintenant. Cela venait simplement du fait que les setters des classes Customer et Delivery n'étaient pas définis, le sérialiseur ne pouvait donc pas placer les value dans les bonnes propriétés !
    Et si cela intéresse quelqu'un, je peux mettre les classes et la string envoyée finales, afin que ça serve aux suivants.
    vendredi 25 novembre 2011 09:29

Toutes les réponses

  • Bonjour,

    Je vous conseille de mettre un point d'arret dans la première ligne de la méthode CreateDelivery et de voir à quelle moment l'Id de l'Appointment est incorrect

    Est-ce que le memoryStream ms est correct ?

    Je mettrai aussi un point d'arret sur la ligne

     deserializedAppointment = (Appointment)ser.ReadObject(ms);

    N'est-ce pas un problème de cast ?

     


    fred on youTube
    PHP MySQL Web Site Creator
    fred
    mercredi 23 novembre 2011 18:30
  • Bonjour Flo,

    Utilisez Fiddler et regardez ce qui se passe dans les requêtes HTTP GET et POST, ça vous aidera à comprendre le problème.

    Pour la sérialisation en JSon. Je vous invite à jeter un coup d’œil à cette documentation.

    Bien cordialement,


    aelassas.free.fr
    mercredi 23 novembre 2011 23:07
    Auteur de réponse
  • Bonjour.

    Tout d'abord merci pour vos réponses. J'ai continué à chercher un peu en prenant en compte vos remarques et je suis toujours dans une impasse.

    J'ai effectué les tests suivants afin de savoir si la sérialisation fonctionne correctement :

    • Création d'une classe basique
      [DataContract]
          public class ClassSimple
          {
              private string _name;
              private int _age;
              private Person _person;
              private string _lastname;
      
              [DataMember (Name="name", Order=1)]
              public string name { get; set; }
      
              [DataMember (Name="age", Order=2)]
              public int age { get; set; }
      
              [DataMember (Name="person", Order=3)]
              public Person person { get; set; }
      
              [DataMember (Name="lastname", Order=4)]
              public string lastname { get; set; }
      
              public ClassSimple()
              {
      
              }
      
              public ClassSimple(string Name, int Age, Person Personne, string LastName)
              {
                  _name = Name;
                  _age = Age;
                  _person = Personne;
                  _lastname = LastName;
              }
          }
      
          [DataContract]
          public class Person
          {
              private string _adr;
              private string _phone;
      
              [DataMember (Name="adr", Order=1)]
              public string adr { get; set; }
      
              [DataMember (Name="phone", Order=3)]
              public string phone { get; set; }
      
              public Person()
              {
      
              }
      
              public Person(string Adr, string Phone)
              {
                  _adr = Adr;
                  _phone = Phone;
              }
          }
      
    • Et test de sérialisation d'une chaine de caractère faite à la mano :
    • public String CreateDelivery(Stream Appointment)
      {
                      string res = "{\"name\":\"Bill\",\"age\":\"32\",\"person\":{\"adr\":\"test\",\"phone\":\"0102030405\"}, \"lastname\":\"Roger\"}";
      
                      ClassSimple newClass = new ClassSimple();
                      MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(res));
                      DataContractJsonSerializer ser = new DataContractJsonSerializer(newClass.GetType());
                      newClass = ser.ReadObject(ms) as ClassSimple;
      
                      return "Received: " + res + " Name : " + newClass.name + " Age : " + newClass.age
                                          + " Adr : " + newClass.person.adr + " Phone : " + newClass.person.phone
                                          + " Lastname : " + newClass.lastname;
      }
      
      Et les informations sont biens retournées comme il faut. La sérialisation fonctionne donc bien.

    Cependant dès lors que je souhaite sérialiser ma JSONStringer, cela ne fonctionne pas du tout, et l'Id appointment que je veux voir afficher reste désespérement à 0.

    Ainsi quelques questions me viennent à l'esprit :

    • Ceci peut-il venir d'un problème au niveau des types utilisés (Datetime, Boolean entre autre) pour les dates de l'Appointment et du Delivery ?
    • Comment puis-je vérifier que mon ms est correct ? Obligé de passer par une page web de test ou Fiddler peut être mon ami sur ce coup ?
    • Enfin, concernant Fiddler. Je suis un novice sur ce logiciel et pour le moment, je n'utilise que les parties "Inspectors" et "Request Builder" afin d'envoyer un requête POST et vérifier le retour de la méthode. Fiddler propose-t-il plus d'informations au sujet de la requête POST envoyée que seul le résultat ?

    Cordialement.

    jeudi 24 novembre 2011 10:19
  • Bonjour,

    Je vous invite à jeter un coup d'oeil à ces Webcasts tirés du site officiel de Fiddler sur mon blog.

    Cordialement,


    aelassas.free.fr
    jeudi 24 novembre 2011 13:09
    Auteur de réponse
  • Bonjour,

    Comme je le pensais dans mon message précédent, le désérialiseur rencontrait un soucis au niveau du format des dates passées. Il ne comprend pas le format de date lisible pour un humain, à savoir "25/11/2011 10:25:00". Il faut passer dans les champs DateTime la date au format Timestamp de cette manire : "\/(Date:1322298900000+0000)\/" afin que la Date soit retranscrite dans la propriété correspondante comme il se doit.

    Cependant, je rencontre un nouveau soucis. J'ai deux objets présents dans l'objet Appointment (Customer et Delivery) et ces objets restent à null lors de la désérialisation.
    Manquerait-il un champ dans ma JSONStringer afin d'indiquer au désérialiseur à quels objets correspondent les pairs "key:value" ?

    En tout cas, merci de votre aide, cela m'a permis d'en apprendre plus sur Fiddler et le fonctionnement du DataContractJsonSerializer.
    Cordialement.

    Edit : mon problème est résolu et le DataContractJsonSerializer fonctionne correctement maintenant. Cela venait simplement du fait que les setters des classes Customer et Delivery n'étaient pas définis, le sérialiseur ne pouvait donc pas placer les value dans les bonnes propriétés !
    Et si cela intéresse quelqu'un, je peux mettre les classes et la string envoyée finales, afin que ça serve aux suivants.
    vendredi 25 novembre 2011 09:29
  • Bonjour, accessoirement je ne comprenais pas pourquoi on prenait en charge soi-même la désérialisation. Si on passe directement un Appointment, WCF n'est il pas censé prendre en charge de lui-même le transfert ?

    Ou est-ce parce que du côté mobile on a des restrictions la partie client WCF étant simplifié pour épargner des ressources ?

     

     


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
    vendredi 25 novembre 2011 22:47
    Modérateur