contrats WCF - espaces de noms et SerializationExceptions
-
19-09-2019 - |
Question
J'utilise un service web tiers qui offre les appels et les réponses suivantes
http://api.athirdparty.com/rest/foo?apikey=1234
<response>
<foo>this is a foo</foo>
</response>
et
http://api.athirdparty.com/rest/bar?apikey=1234
<response>
<bar>this is a bar</bar>
</response>
Ceci est le contrat et les types, j'ai écrit
[ServiceContract]
[XmlSerializerFormat]
public interface IFooBarService
{
[OperationContract]
[WebGet(
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "foo?key={apikey}")]
FooResponse GetFoo(string apikey);
[OperationContract]
[WebGet(
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "bar?key={apikey}")]
BarResponse GetBar(string apikey);
}
[XmlRoot("response")]
public class FooResponse
{
[XmlElement("foo")]
public string Foo { get; set; }
}
[XmlRoot("response")]
public class BarResponse
{
[XmlElement("bar")]
public string Bar { get; set; }
}
et mon client ressemble à ceci
static void Main(string[] args)
{
using (WebChannelFactory<IFooBarService> cf = new WebChannelFactory<IFooBarService>("thirdparty"))
{
var channel = cf.CreateChannel();
FooResponse result = channel.GetFoo("1234");
}
}
Quand je lance ce que j'obtenir l'exception suivante
Impossible de désérialiser corps XML avec le nom de la racine 'réponse' et espace de noms racine '' (pour le fonctionnement 'getFoo' et le contrat ( 'IFooBarService', « http://tempuri.org/ ')) en utilisant XmlSerializer. Assurez-vous que le type correspondant au XML est ajouté à la collection des types connus du service.
Si je commente l'opération de GetBar
de IFooBarService
, il fonctionne très bien. Je sais que je manque un concept important ici - ne savent pas tout à fait ce qu'il faut chercher. Quelle est la bonne façon de construire mes types de contrat, de sorte qu'ils puissent être correctement désérialisé?
La solution
Je dirais que votre service tiers est mal cassé. Il y a une collision d'espace de noms ici -. Il y a deux éléments nommés response
mais avec différents types de schéma XML
Je pense que vous allez avoir à ne pas utiliser toute technologie .NET qui implique désérialisation ce XML. Il n'y aurait aucun moyen de dire .NET dans quel type .NET désérialiser le XML.
Vous aurez juste à le faire à la main. LINQ to XML est à portée de main à cet effet.
Autres conseils
Vous pouvez essayer avec la classe de réponse comme ceci:
[XmlRoot("response")]
public class Response
{
[XmlElement("foo")]
public string Foo { get; set; }
[XmlElement("bar")]
public string Bar { get; set; }
}