WCF contracts - namespaces and SerializationExceptions

六眼飞鱼酱① 提交于 2019-12-24 09:50:57

问题


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

Unable 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?


回答1:


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.




回答2:


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; }
}


来源:https://stackoverflow.com/questions/2417721/wcf-contracts-namespaces-and-serializationexceptions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!