Сериализация XML - отсутствует префикс пространства имен на стороне клиента

Я создал веб-службу .NET, которая возвращает объект, скажем, класс "getResponse".

WS возвращает следующий ответ...

<getResponse xmlns="http://tempuri.org/getCustomer/wsdl/">
   <Result xmlns="http://tempuri.org/getCustomer/">
      <ResultCode>OK</ResultCode>
      <ErrorsList/>
   </Result>  
</getResponse>

в то время как клиент фактически ожидает следующего... (обратите внимание на префикс «mes-root:»)

<mes-root:getResponse xsi:schemaLocation="http://tempuri.org/getCustomer/ getCustomer_V200906.xsd" xmlns:mes-root="http://tempuri.org/getCustomer/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <mes-root:Result>
  <mes-root:ResultCode/>
  <mes-root:ErrorsList/>
 </mes-root:Result>
</mes-root:getResponse>

Как я могу это сделать? Нужно ли мне устанавливать определенные атрибуты сериализации XML в классе getResponse, чтобы префикс mes-root отображался на стороне клиента?

РЕДАКТИРОВАТЬ: я нашел аналогичный вопрос по следующему адресу http://forums.asp.net/t/1249049.aspx. Честно говоря, я не совсем понимаю, и я не могу заставить его работать.


person Preets    schedule 20.03.2009    source источник


Ответы (2)


В обычных условиях именно клиент должен соответствовать типу ответа, отправляемого веб-службой. Однако ваш случай выглядит иначе, поскольку вы создаете веб-сервис, который предоставляет уже существующему клиенту форматированный ответ.

Чтобы решить проблему префикса пространства имен, ссылка, которую вы упомянули в своем вопросе, обеспечивает соответствующее решение; Вам нужно будет «направлять» XmlSerializer во время процесса сериализации, и вы можете сделать это, указав атрибут XmlNamespaceDeclarations для свойства, которое возвращает объект типа XmlSerializerNamespaces. Свойство также должно быть устанавливаемым, иначе пространства имен не будут применяться.

Когда вы добавите следующий код в свой класс getResponse, ответ xml будет соответствовать ожидаемому формату в вашем примере:

[XmlNamespaceDeclarations()] 
public XmlSerializerNamespaces xmlsn 
{ 
  get 
  { 
    XmlSerializerNamespaces xsn = new XmlSerializerNamespaces(); 
    xsn.Add("mes-root", "http://tempuri.org/getCustomer/"); 
    return xsn; 
  } 
  set 
  {
  //Just provide an empty setter. 
  } 
} 

Анализ класса WSDL, сгенерированного для такого веб-сервиса, показывает следующий метод («GetMyResponse» — это имя, которое я дал методу WS, который возвращает объект GetResponse):

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/getCustomer/GetMyResponse", RequestNamespace = "http://tempuri.org/getCustomer/", ResponseNamespace = "http://tempuri.org/getCustomer/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] 
public GetResponse GetMyResponse() 
{ 
  object[] results = this.Invoke("GetMyResponse", new object[-1 + 1]); 
  return (GetResponse)results(0); 
}

Я считаю, что атрибуты RequestNamespace и ResponseNamespace имеют значение.

Надеюсь, это устранит некоторые проблемы в понимании лежащей в основе сериализации Xml, которая здесь имеет место.

Изменить (после комментариев)


Вот ответ, который я получил через свой тестовый веб-сервис:

<?xml version="1.0" encoding="utf-8"?>
<mes-root:GetResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mes-root="http://tempuri.org/getCustomer/">
  <mes-root:Result>OK</mes-root:Result>
  <mes-root:ErrorsList>
    <mes-root:string>SomeErrors</mes-root:string>
    <mes-root:string>SomeMoreErrors</mes-root:string>
  </mes-root:ErrorsList>
</mes-root:GetResponse>
person Cerebrus    schedule 21.03.2009
comment
@Cerebrus, спасибо за ответ. Он работал с XmlNamespaceDeclarations, однако по какой-то причине он работает только в том случае, если XmlSerializerNamespaces инициализирован во время создания класса. Довольно странно. Тем не менее, можно ли добавить к корневому элементу GetResponse префикс mes-root? - person Preets; 24.03.2009
comment
@Preets: я создал базовый образец, чтобы проверить этот сценарий, прежде чем отвечать. Это вообще не требовало инициализации XmlSerializerNamespaces. Кроме того, WS вернул результат, в котором префикс mes:root был добавлен ко всем элементам, включая корневой элемент. - person Cerebrus; 24.03.2009
comment
@Cerebrus, какую версию .net вы используете? - person Preets; 24.03.2009
comment
Я работал с VS2003 .NET 1.1 / Я попробую с VS 2008 .Net 3.5 и посмотрю, есть ли разница! - person Preets; 24.03.2009
comment
Cerebrus, я попробовал очень простой веб-сервис HelloWorld в версии 3.5, и получил следующий ответ (пожалуйста, см. следующий комментарий) - person Preets; 24.03.2009
comment
‹HelloWorldResult xmlns:mes-root=tempuri.org/getCustomer› ‹mes-root:MyProperty›MyProp‹ /mes-root:MyProperty› ‹/HelloWorldResult› - person Preets; 24.03.2009
comment
@Preets: я не думаю, что мы сможем найти удовлетворительное решение с помощью комментариев. Я предлагаю отправить мне электронное письмо, если это действительно важно. Вы можете найти мою электронную почту, если проведете небольшое расследование через мой профиль. (Я не размещаю здесь свою электронную почту... Я спам-фоб ;-)) - person Cerebrus; 24.03.2009
comment
Отредактированный пост, чтобы включить ответ WS, который я получаю. - person Cerebrus; 25.03.2009
comment
@Cerebrus, сегодня мой счастливый день! Я перенес код на 3.5 и вуаля! Работает как часы ! Я предполагаю, что проблема только с .net framework 1.1! Большое спасибо за ваш ответ! Помогли мне двигаться в правильном направлении! - person Preets; 26.03.2009
comment
Поздравляю, Притс! И добро пожаловать в клуб Lucky Day! Рад помочь. :П - person Cerebrus; 26.03.2009
comment
Только что наткнулся на это (снова) и помог мне решить огромную проблему. Спасибо :) - person cjk; 23.04.2010

Итак, второй образец теперь является допустимым XML, но семантически он не эквивалентен первому образцу, потому что первый имеет два пространства имен, а второй — только одно.

Проблема в том, что вы отправляете XML, который семантически неверен, или в том, что они специально требуют, чтобы префикс назывался mes-root?

person Greg Beech    schedule 20.03.2009
comment
@Greg, я обновил выходной ответ объявлением ns. Но я не уверен, как генерировать префиксы для пользователя. - person Preets; 20.03.2009
comment
Нужно ли предоставлять некоторую информацию о сериализации для класса getResponse? - person Preets; 20.03.2009
comment
Только что обновил мой ответ - ваши образцы XML все еще не эквивалентны, поэтому вы должны сначала решить, является ли это проблемой! - person Greg Beech; 20.03.2009
comment
@Greg, к сожалению, это последнее ... содержание правильное, но префикс отсутствует ... тестовая среда на стороне клиента - это веб-методы. В идеале они должны заниматься этим вопросом? - person Preets; 20.03.2009
comment
Любая XML-библиотека, соответствующая стандартам, не должна заботиться о префиксе (или даже о том, используется ли префикс), если содержимое семантически эквивалентно. Если вы уверены, что содержимое эквивалентно, то я бы сказал, что это проблема клиента, а не ваша, и ему нужно отсортировать свои XML-библиотеки! - person Greg Beech; 20.03.2009