Контракты WCF - пространства имен и сериализация.
-
19-09-2019 - |
Вопрос
Я использую стороннюю веб -сервис, который предлагает следующие вызовы и ответы
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 с именем корня «ответ» и корневое пространство имен '' (для операции «getfoo» и contract («ifoobarservice», 'http://tempuri.org/')) Использование XMLSerializer. Убедитесь, что тип, соответствующий XML, добавляется в коллекцию известных типов Сервиса.
Если я прокомментирую GetBar
Операция из IFooBarService
, это работает нормально. Я знаю, что мне здесь не хватает важной концепции - просто не знаю, что искать. Каков правильный способ построить мои типы контрактов, чтобы они могли быть должным образом опустошены?
Решение
Я бы сказал, что ваше стороннее обслуживание сильно сломано. Здесь есть столкновение пространства имен - есть два элемента, названные response
Но с разными типами схемы XML.
Я думаю, что вам придется не использовать какую -либо технологию .NET, которая включает в себя десеризацию этого XML. Не было бы никакого способа сказать .NET, в который тип .NET DeSerialize XML.
Вам просто нужно сделать это вручную. LINQ TO XML удобно для этой цели.
Другие советы
Вы можете попробовать с классом ответов, как это:
[XmlRoot("response")]
public class Response
{
[XmlElement("foo")]
public string Foo { get; set; }
[XmlElement("bar")]
public string Bar { get; set; }
}