Я пытаюсь использовать предоставляемую поставщиком веб-службу AXIS с клиентом WCF. Ожидается, что служба будет иметь элемент запроса / ответа <TXLife>
в качестве корневого элемента тела SOAP (элемент операции не содержит его). Я использую XmlSerializer, потому что в моем контракте с данными есть некоторые особенности схемы ACORD. Например, сервер хочет видеть следующее (... и да, "service" - это имя операции ...):
...<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><TXLife><TXLifeRequest xmlns="">...
Мой клиент генерирует XML с операцией, сериализованной как элемент обертки, подобный этому:
...<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><service xmlns="urn:example.servicecontract"><TXLife><TXLifeRequest xmlns="">...
С тэгом «extra», указывающим операцию в запросе, сервис не может обработать запрос и ошибки. Если я удалю тег <service>
, веб-служба успешно обработает запрос.
К сожалению, служба также отправляет ответ с развернутым тегом <TXLife>
в качестве корневого элемента:
...<soapenv:Body><TXLife xmlns=""><TXLifeResponse>...
Мой десериализатор неправильно обрабатывает ответ, и я получаю null
объект обратно. Я предполагаю, потому что мой клиент ожидает тег-обертку ответа операции сервиса и не получает его. Я не получаю особой помощи от отладчика на уровне десериализации.
Я думал о реализации IClientMessageFormatter или даже IClientMessageInspector для изменения запроса / ответа (например, удалите тег операции из сообщения запроса и добавьте тег ответа в сообщение ответа). Я знаю, что Formatter внедряется как OperationalBehavior, но я не уверен, куда MessageInspector помещается в стек. Может быть, я иду по этому пути неправильно ...
Любое понимание или предложения будут оценены. Простите, это моя первая попытка использования услуг WCF, и я постепенно прощупываю свой путь. К сожалению, все об этом сервисе, кажется, "на заказ".
Мой сервисный контракт:
[XmlSerializerFormat]
[ServiceContract(Namespace="urn:example.servicecontract")]
public interface IPayoutServiceContract
{
[OperationContract]
TXLife service([MessageParameter(Name = "TXLife")]TXLife request);
}
Часть службы WSDL:
<wsdl:types><schema targetNamespace="urn:Tx103Service" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><import id="tx" namespace="http://ACORD.org/Standards/Life/2" schemaLocation="../acord/TXLife2.8.92.xsd" /></schema></wsdl:types><wsdl:message name="serviceRequest"><wsdl:part element="tx:TXLife" name="acordRequest" /></wsdl:message><wsdl:message name="serviceResponse"><wsdl:part element="tx:TXLife" name="acordResponse" /></wsdl:message><wsdl:portType name="LifeWebService"><wsdl:operation name="service"><wsdl:input message="impl:serviceRequest" name="serviceRequest" /><wsdl:output message="impl:serviceResponse" name="serviceResponse" /></wsdl:operation></wsdl:portType>
Обновление:
Сначала я попытался использовать декоратор MessageContract(isWrapped=false)
в прокси-классе (интерфейс запрещает это). Это ничего не сделало. Я также попробовал ароматы BodyStyle = WebMessageBodyStyle.Bare
, тоже ничего. Я предполагаю, что это связано с использованием XMLSerializer. Мне кажется, что нет простого способа «украсить» мой способ решения этой проблемы.
Кстати: мой сервисный контракт, контракт на передачу данных и прокси-клиент находятся в отдельных проектах в соответствии с этой рекомендацией, которая показалась мне твердой:
сообщение в блоге Мигеля Кастро
Update2:
Я создал классы-оболочки запросов / ответов, украшенные тегами MessageContract / MessageBodyMember. Теперь XML генерируется как ожидалось. Все еще получаю нулевой объект в ответе ...
Update3:
«Пустые» объекты в моем ответе фактически присутствовали в ответе XML, но не были десериализованы, потому что сериализатор искал их как квалифицированные объекты. Я изменил их на неквалифицированные, и после этого мои объекты обнаружились очень хорошо.