WCF contracts - namespaces and SerializationExceptions
I am using a third party web service that offers the following calls and responses
http://api.athirdparty.com/rest/foo?apikey=1234
<response>
<foo>this is a foo</foo>
</response>
and
http://api.athirdparty.com/rest/bar?apikey=1234
<response>
<bar>this is a bar</bar>
</response>
This is the contract and supporting types I wrote
[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; }
}
and then my client looks like this
static void Main(string[] args)
{
using (WebChannelFactory<IFooBarService> cf = new WebChannelFactory<IFooBarService>("thirdparty"))
{
var channel = cf.CreateChannel();
FooResponse result = channel.GetFoo("1234");
}
}
When I run this I get the following exception
Una开发者_高级运维ble to deserialize XML body with root name 'response' and root namespace '' (for operation 'GetFoo' and contract ('IFooBarService', 'http://tempuri.org/')) using XmlSerializer. Ensure that the type corresponding to the XML is added to the known types collection of the service.
If I comment out the GetBar
operation from IFooBarService
, it works fine. I know I'm missing an important concept here - just don't know quite what to look for. What is the proper way to construct my contract types, so that they can be properly deserialized?
I'd say your third-party service is badly broken. There's a namespace collision here - there are two elements named response
but with different XML Schema types.
I think you're going to have to not use any .NET technology that involves deserializing this XML. There would be no way to tell .NET into which .NET type to deserialize the XML.
You'll just have to do it by hand. LINQ to XML is handy for this purpose.
You can try with response class like this:
[XmlRoot("response")]
public class Response
{
[XmlElement("foo")]
public string Foo { get; set; }
[XmlElement("bar")]
public string Bar { get; set; }
}
精彩评论