2014-05-16 2 views
3

Je reçois cette erreur quand je tente d'appeler un service WCF:WCF client Exception: erreur en essayant de paramètre désérialiser

Le formatter a lancé une exception tout en essayant de désérialiser le message : Il y avait une erreur tout en essayant de désérialiser le paramètre http://tempuri.org/:ResultValue. Le message InnerException était 'Erreur dans la ligne 1 position 1741. Elément ' htp: //schemas.microsoft.com/2003/10/Serialization/Arrays: anyType ' contient des données d'un type qui correspond au nom ' htp : //schemas.datacontract.org/2004/07/DataAccess: Personne '. Le désérialiseur n'a aucune connaissance d'aucun type correspondant à ce nom. Envisagez d'utiliser DataContractResolver ou ajoutez le type correspondant à 'Personne' à la liste des types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en l'ajoutant à la liste des types connus passés à DataContractSerializer. '.

J'ai un projet Interfaces avec les définitions suivantes:

public interface IPerson 
{ 
    string Name { get; set; } 
} 

public interface IPersonExtended : IPerson 
{ 
    // If I remove the List of IPerson property, it works fine 
    List<IPerson> Contacts { get; set; } 
} 

J'ai un projet DataAccess qui implémente les interfaces:

public class Person : IPerson 
{ 
    public string Name { get; set; } 
} 

public class PersonExtended : IPersonExtended 
{ 
    public string Name { get; set; } 
    private List<IPerson> mContacts = new List<IPerson>(); 

    // If I remove the List of IPerson property, it works fine 
    public List<IPerson> Contacts 
    { 
     get { return mContacts; } 
     set { mContacts = value; } 
    } 
} 

Mon contrat de service ressemble à ceci:

[ServiceContract] 
[ServiceKnownType(typeof(Person))] 
[ServiceKnownType(typeof(PersonExtended))] 
public interface IMyService 
{ 
    [OperationContract] 
    ServiceCallResult<GetPeopleResponse> GetPeople(GetPeopleRequest request); 
} 

Mon service ks comme:

public class MyService : IMyService 
{ 
    public ServiceCallResult<GetPeopleResponse> GetPeople(GetPeopleRequest request) 
    { 
     GetPeopleResponse response = new GetPeopleResponse(); 
     // Get Some people that have contacts 
     response.People = GetPeopleFromSomewhere(); 

     ServiceCallResult<GetPeopleResponse> result = 
      new ServiceCallResponse<GetPeopleResponse> { ResultValue = response }; 

     return result; 
    } 
} 

Et mon objet de réponse ressemble à:

[DataContract] 
[KnownType(typeof(PersonExtended))] 
[KnownType(typeof(Person))] 
[KnownType(List<Person>))] 
[KnownType(List<PersonExtended))] 
public class GetPeopleResponse 
{ 
    [DataMember] 
    public List<PersonExtended> People { get; set; } 
} 

L'objet de réponse est tout simplement enveloppé dans un objet MessageContract qui contient des informations d'état, etc.

EDIT Si Je supprime la propriété Contact (List) à travers l'ensemble du workflow, cela fonctionne très bien. Je me demande si cela est lié à essayer d'utiliser une propriété avec une liste à une interface au lieu d'un objet concret, mais je ne suis pas sûr de savoir comment contourner cela avec ma structure de projet sans ajouter de référence circulaire.

Répondre

2

vous avez besoin [DataContract] et [DataMember] sur la classe Person

[DataContract] 
public class Person : IPerson 
{ 
    [DataMember] 
    public string Name { get; set; } 
} 

KnownTypeAttribute est censé vous permettre de désigner classe dérivée acceptable pour un DataContract donné. Il spécifie les types qui doivent être reconnus par le DataContractSerializer lorsque Sérialiser ou Désérialiser un type donné.

GetPeopleResponse ne provient pas de Person ou PersonExtended ...

De plus, il y a beaucoup de choses dans votre code qui n'a pas de sens du tout pour moi ... Voici quelque chose qui fait sens pour moi...

public interface IPerson { 
    string Name { get; set; } 
} 

public interface IPersonExtended : IPerson { 
    List<IPerson> Contacts { get; set; } 
} 

[DataContract] 
public class Person : IPerson { 
    [DataMember] 
    public string Name { get; set; } 
} 

[DataContract] 
public class PersonExtended : Person, IPersonExtended { 
    [DataMember] 
    public List<Person> Contacts { get; set; } 

    public PersonExtended() { 
     Contacts = new List<Person>(); 
    } 
} 

[ServiceContract] 
public interface IMyService { 
    [OperationContract] 
    IList<PersonExtended> GetAllPeople(); 
} 

public class MyService : IMyService 
{ 
    private IList<PersonExtended> _people; 

    public MyService() { 
     _people = new IList<PersonExtended>(); 
    } 

    public IList<PersonExtended> GetAllPeople() { 
     return _people 
    } 
} 
+0

Je ne pense pas que ce soit tout à fait ça. J'ai mis à jour ma question. Cela représente une version simplifiée de mon objet propriétaire. L'objet 'ServiceCallResult' est juste un wrapper contenant des informations d'état, etc. –

+0

vous avez une déclaration de retour à la fin de votre classe de service qui me dit que vous ne savez pas ce que vous faites ... la classe de service n'implémente pas non plus la fonction déclarée par l'interface. – furier

+0

En fait, ce n'est pas que je ne sais pas ce que je fais. C'était un simple problème de couper/coller. J'ai évidemment juste laissé de côté la ligne avec la fonction def, qui doit être là pour satisfaire l'interface. –

Questions connexes