Контракты WCF - пространства имен и исключения SerializationExceptions - PullRequest
1 голос
/ 10 марта 2010

Я использую сторонний веб-сервис, который предлагает следующие звонки и ответы

http://api.athirdparty.com/rest/foo?apikey=1234

<response>
  <foo>this is a foo</foo>
</response>

и

http://api.athirdparty.com/rest/bar?apikey=1234

<response>
  <bar>this is a bar</bar>
</response>

Это контракт и вспомогательные типы, которые я написал

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

и тогда мой клиент выглядит так

static void Main(string[] args)
{
    using (WebChannelFactory<IFooBarService> cf = new WebChannelFactory<IFooBarService>("thirdparty"))
    {
        var channel = cf.CreateChannel();
        FooResponse result = channel.GetFoo("1234");
    }
}

Когда я запускаю это, я получаю следующее исключение

Невозможно десериализовать тело XML с корневым именем 'response' и корневым пространством имен '' (для операции 'GetFoo' и контракта ('IFooBarService', 'http://tempuri.org/')) с использованием XmlSerializer. Убедитесь, что тип соответствует XML добавлен в коллекцию известных типов сервиса.

Если я закомментирую операцию GetBar с IFooBarService, она работает нормально. Я знаю, что здесь отсутствует важная концепция - просто не знаю, что искать. Как правильно построить типы моих контрактов, чтобы их можно было правильно десериализовать?

Ответы [ 2 ]

2 голосов
/ 12 марта 2010

Я бы сказал, что ваш сторонний сервис сильно сломан. Здесь есть конфликт пространства имен - есть два элемента с именем response, но с разными типами схемы XML.

Я думаю, вам не придется использовать какую-либо технологию .NET, которая предполагает десериализацию этого XML. Не было бы никакого способа указать .NET, в какой тип .NET десериализовать XML.

Тебе просто нужно будет сделать это вручную. LINQ to XML удобен для этой цели.

0 голосов
/ 09 ноября 2011

Вы можете попробовать с классом ответа, как это:

[XmlRoot("response")]
public class Response
{
    [XmlElement("foo")]
    public string Foo { get; set; }

    [XmlElement("bar")]
    public string Bar { get; set; }
}
...