J'ai un service WCF en place.
Le fonctionnement normal verrait le serveur effectuer un certain traitement en renvoyant un objet XactTaskIn rempli au client via un rappel. J'ai ce travail ok.
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 rappel, j'obtiens l'exception suivante levée.
Exception - "Type" XactException "avec le nom du contrat de données" XactException: http: //schemas.datacontract.org/2004/07/ "n'est pas prévu. Envisagez d'utiliser un DataContractResolver ou ajoutez des types non connus statiquement à la liste des types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en les ajoutant à la liste des types connus transmis à DataContractSerializer. " (System.Runtime.Serialization.SerializationException) Message d'exception = "Tapez 'XactException' avec le nom du contrat de données 'XactException: http: //schemas.datacontract.org/2004/07/' n'est pas prévu. Envisagez d'utiliser un DataContractResolver ou ajoutez-en un types non connus statiquement dans la liste des types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en les ajoutant à la liste des types connus transmis à DataContractSerializer. ", Exception Type =" 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 donc le commentaire de Daniel m'a aidé.
Il semble maintenant que le serveur envoie le rappel au client, mais le client lève l'exception suivante.
- Caught: "Le formateur a levé une exception en essayant de désérialiser le message: il y a eu une erreur en essayant de désérialiser le paramètre http://tempuri.org/:taskIn . Le message InnerException était 'Erreur en ligne 1 position 960. L'élément 'http://schemas.datacontract.org/2004/07/:returnData' contient des données d'un type qui correspond au nom 'http://schemas.datacontract.org/2004/07/:XactException ". Le désérialiseur ne connaît aucun type mappé à ce nom. Envisagez d'utiliser un DataContractResolver ou ajoutez le type correspondant à" XactException "à la liste des types connus - par exemple, en utilisant l'attribut KnownTypeAttribute ou en l'ajoutant à l'attribut liste des types connus transmis à DataContractSerializer. ". Veuillez consulter InnerException pour plus de détails." (System.ServiceModel.Dispatcher.NetDispatcherFaultException) Message d'exception = "Le formateur a levé une exception lors de la désérialisation du message: une erreur s'est produite lors de la désérialisation du paramètre http://tempuri.org/:taskIn =. Le message InnerException était 'Erreur dans la ligne 1 position 960. L'élément' http://schemas.datacontract.org/2004/07/:returnData 'contient des données d'un type qui correspond au nom' http: // schemas. datacontract.org/2004/07/:XactException ". Le désérialiseur n'a connaissance d'aucun type mappé à ce nom. Envisagez d'utiliser un DataContractResolver ou ajoutez le type correspondant à" XactException "à la liste des types connus - par exemple, en en utilisant l'attribut KnownTypeAttribute ou en l'ajoutant à la liste des types connus transmis à DataContractSerializer. ". Veuillez consulter InnerException pour plus de détails.", Exception Type = "System.ServiceModel.Dispatcher.NetDispatcherFaultException"
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 éventuellement s'y trouver, afin de pouvoir indiquer au client (via le WSDL) quels sont tous les types. Pour tout type/tous les types non "natifs" (tout ce qui n'est pas entier, chaîne, DateTime, etc.), vous devrez ajouter un attribut [KnownType] pour chaque type possible qui pourrait être renvoyé 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 crée le WSDL pour le service, il saura ajouter XactException à la liste des types de données, et le sérialiseur saura également rechercher ces classes.
Note latérale; 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]!
Votre client attend une XactTaskIn et non une XactException.
Vous devez modifier votre XactTaskIn pour pouvoir transmettre un objet d'exception à votre client.
Supprimez votre contrat de données d'exception et ajoutez le type XactException à votre classe XactTaskIn en tant que membre de données
Des 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
en awesomeSTring
provoquera la rupture de la sérialisation. La raison en est que les nouvelles données ne peuvent plus être validées par rapport aux anciennes données. Le correctif consiste à utiliser l'ancienne version attendue par le serveur/client.