Question

J'ai un contrat de service qui définit une méthode avec un paramètre de type System.Object (xs: anyType dans le WSDL). Je veux pouvoir passer des types simples ainsi que des types complexes dans ce paramètre. Les types simples fonctionnent bien, mais lorsque j'essaie de passer un type complexe défini dans mon WSDL, le message d'erreur suivant s'affiche:

L'élément ' http://tempuri.org/:value ' contient des données de ' http://schemas.datacontract.org/2004/07/MyNamespace:MyClass ' contrat de données. Le désérialiseur n'a connaissance d'aucun type correspondant à ce contrat. Ajoutez le type correspondant à "MyClass" à la liste des types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en l'ajoutant à la liste des types connus transmis à DataContractSerializer.

L'ajouter en tant que type connu n'aide pas, car il est déjà dans mon WSDL. Comment puis-je passer un objet d'un type complexe via un "xs: anyType"? paramètre?

Plus d'infos:

Je pense que cela fonctionne avec NetDataContract, mais je ne peux pas l'utiliser car mon client est Silverlight.

J'ai vu des références à des types complexes élargissant explicitement xs: anyType, mais je ne sais pas comment faire en sorte que WCF génère un WSDL faisant cela, et je ne sais pas si cela aiderait même.

Merci

Était-ce utile?

La solution 3

J'ai résolu ce problème en utilisant l'attribut ServiceKnownType. J'ajoute simplement mon type complexe en tant que type de service connu sur mon contrat de service, et l'erreur disparaît. Je ne sais pas pourquoi cela n'a pas fonctionné la dernière fois que je l'ai essayé.

Cela ne semble pas affecter le WSDL de quelque manière que ce soit, donc je soupçonne que le flux sérialisé doit présenter une différence qui informe le désérialiseur que l'objet peut être désérialisé à l'aide de mon type.

Autres conseils

NetDataContract fonctionne parce que NetDataContractSerializer inclut des informations de type.

L'attribut KnownType indique à DataContractSerializer comment désérialiser le message. S'agissant d'une implémentation spécifique, il s'agit d'informations en plus de celles définies par le contrat public et qui n'appartiennent pas au WSDL.

Vous ne pourrez jamais transmettre un type de données ancien, car le désérialiseur doit identifier le type approprié et créer une instance.

Vous pourrez peut-être dériver vos types connus au moment de l'exécution plutôt que de les avoir codés en dur dans DataContract. Regardez ici pour un exemple.

J'espère que cela vous aidera. J'ai vu un de mes collègues utiliser ce code pour envoyer des types de données complexes. Pour moi, c'est assez simple. Cela a été utilisé avec basicHttpBinding et cela fonctionne plutôt bien avec MOSS BDC ainsi que d'autres applications qui utilisent la liaison de base.

  1. Créer un contrat de données basé sur une classe générique
  2. Utilisez le contrat de données lorsque les informations doivent être envoyées

    [DataContract (Namespace = " http: //Service.DataContracts ", Name = " ServiceDataContractBase " )] Classe publique ServiceDataContract {

    public ServiceDataContract() { }
    
    public ServiceDataContract(TValueType Value)
    {
        this.m_objValue = Value;
    }
    
    private TValueType m_objValue;
    
    [DataMember(IsRequired = true, Name = "Value", Order = 1)]
    public TValueType Value
    {
        get { return m_objValue; }
        set { m_objValue = value; }
    }
    

    }

Utilisez ce contrat de données chaque fois que cela est nécessaire dans les fonctions WCF qui renvoient le type de données complexe. Par exemple:

public ServiceDataContract<string[]> GetStrings()
{
    string[] temp = new string[10];
    return new ServiceDataContract<string[]>(temp);
}

Mise à jour: ServiceDataContract est une classe générique utilisant TValueType. Il n'apparaît pas à cause d'un problème avec le rendu du code HTML.

Essayez d’utiliser le contrat de données de substitution pour mapper un objet non pris en charge qui est spécifique à un réseau de points ou non interopérable. Voir MSDN

Pour l’instant, j’ai résolu ce problème en créant un nouveau type de contrat de données pouvant envelopper un autre type de contrat de données ou un type simple. Au lieu de passer le type Object, je passe maintenant cette classe wrapper. Cela fonctionne bien, mais j'aimerais quand même savoir s'il existe une solution au problème initial.

J'ai essayé d'ajouter l'attribut ServiceKnownType, en spécifiant le type que je tente de transmettre, mais j'obtiens toujours la même erreur. J'ai également essayé d'ajouter l'attribut KnownType à mon contrat de données (qui semblait idiot parce que c'était du même type que le contrat de données). Je suppose que leur ajout au moment de l'exécution n'aidera pas si leur ajout à la compilation n'aide pas.

Si j'étendais un autre type complexe, il me semble que j'aimerais ajouter l'attribut KnownType à ce type de base. Mais comme mon type de base est Object, je ne vois aucun moyen de le faire.

En ce qui concerne les substituts, il me semble qu’ils sont utilisés pour les types d’emballage qui n’ont pas de contrat défini. Dans mon cas cependant, le contrat est défini.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top