48 votes

Unxpected Type - Serialization Exception

J'ai un service WCF en place.

Dans le cadre d'un fonctionnement normal, le serveur effectue un traitement et renvoie un objet XactTaskIn rempli au client via un callback. J'ai réussi à faire fonctionner ce système.

Mon problème est que lorsque j'essaie de définir la variable returnData sur une XactException remplie et que j'essaie de renvoyer le XactTaskIn au client via le callback, j'obtiens l'exception suivante.

Exception - "Type 'XactException' avec nom du contrat de données XactException:http://schemas.datacontract.org/2004/07/' n'est pas attendu. Envisagez d'utiliser un DataContractResolver ou ajoutez tous les types non connus statiquement à la liste des types types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en les en les ajoutant à la liste des types connus transmis à DataContractSerializer". (System.Runtime.Serialization.SerializationException) Exception Message = "Type 'XactException' avec nom du contrat de données XactException:http://schemas.datacontract.org/2004/07/' n'est pas attendu. Envisagez d'utiliser un DataContractResolver ou ajoutez tous les types non connus statiquement à la liste des types types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en les en les ajoutant à la liste des types connus transmis à DataContractSerializer", Type d'exception = "System.Runtime.Serialization.SerializationException".

Voici la classe XactTaskIn

[DataContract]
public class XactTaskIn
{
    [DataMember]
    public DateTime timeOut;
    [DataMember]
    public DateTime timeIn;
    [DataMember]
    public string name;
    [DataMember]
    public string responseTo;
    [DataMember]
    public String moduleFromName;
    [DataMember]
    public String moduleFromType;
    [DataMember]
    public String methodFromName;
    [DataMember]
    public object[] originalInputs;
    [DataMember]
    public String returnMethodToCall;
    [DataMember]
    public String returnModuleToCall;
    [DataMember]
    public object returnData;

    public XactTaskIn(DateTime timeOut, DateTime timeIn, string name, string responseTo, String moduleFromName, String moduleFromType, String methodFromName, object[] originalInputs, String returnMethodToCall, String returnModuleToCall, object returnData)
    {
        this.timeOut = timeOut;
        this.timeIn = timeIn;
        this.name = name;
        this.responseTo = responseTo;
        this.moduleFromName = moduleFromName;
        this.moduleFromType = moduleFromType;
        this.methodFromName = methodFromName;
        this.originalInputs = originalInputs;
        this.returnMethodToCall = returnMethodToCall;
        this.returnModuleToCall = returnModuleToCall;
        this.returnData = returnData;
    }
}

Voici la classe XactException :

[DataContract]    
public class XactException
{
    [DataMember]
    string message;

    public XactException(string message)
    {
        this.message = message;
        // Add implementation.
    }
}

Mise à jour :

Ok, le commentaire de Daniel m'a aidé.

Il semble maintenant que le serveur envoie le callback au client, mais que le client lève l'exception suivante.

  • Attrapé : "Le formateur a lancé une exception en essayant de désérialiser le message : Il y a eu une erreur pendant que en essayant de désérialiser le paramètre http://tempuri.org/:taskIn . Le message InnerException est "Error in ligne 1 position 960. Élément http://schemas.datacontract.org/2004/07/:returnData' contient des données provenant d'un type qui correspond au le nom http://schemas.datacontract.org/2004/07/:XactException'. Le désérialiseur n'a pas connaissance aucun type correspondant à ce nom. Envisagez d'utiliser un DataContractResolver ou ajoutez le type correspondant à correspondant à 'XactException' dans la liste des types connus - par exemple, en utilisant la classe attribut KnownTypeAttribute ou en l'ajoutant à la liste des types connus transmis à DataContractSerializer". Pour plus de détails, voir InnerException. détails." (System.ServiceModel.Dispatcher.NetDispatcherFaultException) Exception Message = "The formatter threw an exception en essayant de désérialiser le message : There was an error while en essayant de désérialiser le paramètre http://tempuri.org/:taskIn . Le message InnerException était 'Error in ligne 1 position 960. Élément http://schemas.datacontract.org/2004/07/:returnData contient des données provenant d'un type qui correspond au le nom http://schemas.datacontract.org/2004/07/:XactException'. Le désérialiseur n'a aucune connaissance de aucun type correspondant à ce nom. Envisagez d'utiliser un DataContractResolver ou ajoutez le type correspondant à correspondant à 'XactException' dans la liste des types connus - par exemple, en utilisant l'attribut attribut KnownTypeAttribute ou en l'ajoutant à la liste des types connus transmis à DataContractSerializer'. Veuillez consulter InnerException pour plus détails.", Exception Type = "System.ServiceModel.Dispatcher.NetDispatcherFaultException"

80voto

CodingWithSpike Points 17720

Dans votre classe

    [DataContract]
    public class XactTaskIn

vous avez des propriétés qui renvoient des objets :

        [DataMember]
        public object[] originalInputs;

        [DataMember]
        public object returnData;

WCF doit savoir à l'avance quels types peuvent être possiblement là-dedans, de sorte qu'il puisse dire au client (par le WSDL) quels sont tous les types. Pour tous/toutes les types non 'natifs' (n'importe quoi qui n'est pas int, string, DateTime, etc) vous devrez ajouter un attribut [KnownType] pour chaque type possible qui pourrait être passé en arrière dans ces propriétés d'objet, comme ceci :

    [KnownType(typeof(XactException))]
    [KnownType(typeof(...))]
    [KnownType(typeof(...))]
    [DataContract]
    public class XactTaskIn

De cette façon, lorsque WCF construira le WSDL pour le service, il saura qu'il faut ajouter XactException à la liste des types de données, et le sérialiseur saura qu'il faut rechercher ces classes.


Remarque : si votre client a été construit à l'aide de SrvUtil, Service Reference, ou généré à partir du WSDL d'une manière ou d'une autre, vous devrez reconstruire le client après avoir ajouté les attributs [KnownType] !

0voto

KenL Points 360

Votre client s'attend à un XactTaskIn et non à une XactException.

Vous devez modifier votre XactTaskIn pour pouvoir renvoyer un objet d'exception à votre client.

Laissez tomber votre contrat de données d'exception et ajoutez le type XactException à votre classe XactTaskIn en tant que membre de données.

0voto

Woot4Moo Points 14245

Les exceptions de sérialisation se produisent lorsque les données ont changé, par exemple quelque chose d'aussi trivial que de changer le nom d'un champ de awesomeString a awesomeSTring entraînera une rupture de la sérialisation. La raison en est que les nouvelles données ne peuvent plus être validées par rapport aux anciennes. La solution consiste à utiliser l'ancienne version attendue par le serveur/client.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X