Contratos de WCF: espacios de nombres y concepciones de serialización
-
19-09-2019 - |
Pregunta
Estoy usando un servicio web de terceros que ofrece las siguientes llamadas y respuestas.
http://api.athirdparty.com/rest/foo?apikey=1234
<response>
<foo>this is a foo</foo>
</response>
y
http://api.athirdparty.com/rest/bar?apikey=1234
<response>
<bar>this is a bar</bar>
</response>
Este es el contrato y los tipos de apoyo que escribí
[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; }
}
Y luego mi cliente se ve así
static void Main(string[] args)
{
using (WebChannelFactory<IFooBarService> cf = new WebChannelFactory<IFooBarService>("thirdparty"))
{
var channel = cf.CreateChannel();
FooResponse result = channel.GetFoo("1234");
}
}
Cuando ejecuto esto obtengo la siguiente excepción
No se puede deserializar el cuerpo XML con el nombre de la raíz 'respuesta' y el espacio de nombres raíz '' (para la operación 'getfoo' y contrato ('ifoobarservice', ','http://tempuri.org/')) usando XMLSerializer. Asegúrese de que el tipo correspondiente al XML se agregue a la colección de tipos conocida del servicio.
Si comento el GetBar
operación de IFooBarService
, funciona bien. Sé que me falta un concepto importante aquí, simplemente no sé qué buscar. ¿Cuál es la forma correcta de construir mis tipos de contrato, para que puedan ser deserializados adecuadamente?
Solución
Diría que su servicio de terceros está muy roto. Aquí hay una colisión en el espacio de nombres: hay dos elementos nombrados response
pero con diferentes tipos de esquema XML.
Creo que tendrá que no usar ninguna tecnología .NET que implique deserializar este XML. No habría forma de decirle a .NET en qué .NET tipo de .NET deserializar el XML.
Solo tendrás que hacerlo a mano. Linq a XML es útil para este propósito.
Otros consejos
Puede intentarlo con clase de respuesta como esta:
[XmlRoot("response")]
public class Response
{
[XmlElement("foo")]
public string Foo { get; set; }
[XmlElement("bar")]
public string Bar { get; set; }
}