Как (почему) определение пространства имен с помощью ServiceContract влияет на функциональность - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть ServiceContract следующим образом:

  [ServiceContract]
  public interface IHttpsServer
  {
    [OperationContract] 
    [XmlSerializerFormat]
    void Post(SomeEvent e);
  }

Событие определено так:

  [Serializable]
  [XmlType(Namespace = "")]
  public class SomeEvent 
  {
    [XmlAttribute("flag")]
    public bool m_bFlag;

    [XmlElement("Name")]
    public string m_strName;
    ...
  }

Этот сервис размещен ServiceHost с помощью BasicHttpBinding.

Что я делаю:

  1. запуск веб-службы
  2. добавление ссылки на работающий веб-сервис в клиентском приложении
  3. запуск клиента и отправка SomeEventна сервер.

И в этот момент у меня проблема - пост-функция будет вызвана, но SomeEvent пуст (все пустые поля null).

Но, если у меня пустое пространство имен для ServiceContrat ([ServiceContract(Namespace = "")]), то оно работает нормально.Почему это происходит?

Обновление:

Я выполнил несколько проверок, которые имеют странные результаты:

  1. Когда пространство имен определяется какServiceContract и SomeEvent ([ServiceContract(Namespace = "http://anynamespace")] и [XmlType(Namespace = "http://othernamespace")]), тогда он работает нормально .
  2. Когда пространство имен определяется только ServiceContract ([ServiceContract(Namespace = "http://anynamespace")] и [XmlType(Namespace = "")]),тогда это не работает .
  3. Когда есть пустое пространство имен, определенное обоими ([ServiceContract(Namespace = "")] и [XmlType(Namespace = "")]), тогда это отлично работает .
  4. Когда ServiceContract содержит пустое пространство имен, но для SomeEvent определено пространство имен ([ServiceContract(Namespace = "")] и [XmlType(Namespace = "http://othernamespace")]), тогда оно отлично работает .

1 Ответ

0 голосов
/ 30 ноября 2018

Ну, я полагаю, я нашел причину такого поведения.

Прежде всего, я реализовал IDispatchMessageInspector.Это дало мне возможность отслеживать запросы от клиента.Запросы от клиента выглядят так:

+       request {<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://localhost/</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IHttpsServer/Post</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Post xmlns="http://tempuri.org/">
      <xml flag="true">
        <Name>John</Name>
      </xml>
    </Post>
  </s:Body>
</s:Envelope>}  System.ServiceModel.Channels.Message {System.ServiceModel.Channels.BufferedMessage}

Через некоторое время я заметил, что для узла Post определено пространство имен по умолчанию, а для узла 'xml' не определено пространство имен.Итак, у нас есть то, что xml в этом примере является частью xmlns="http://tempuri.org/", а не пустым пространством имен, как оно определено.

Чтобы проверить мое предложение, я сгенерировал код клиента и вручную добавил XmlType атрибут к объявлению SomeEvent:

  [System.Xml.Serialization.XmlType(Namespace = "")]

После этого изменения я получил следующий запрос:

+       request {<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://localhost/</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IHttpsServer/Post</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Post xmlns="http://tempuri.org/">
      <xml flag="true">
        <Name xmlns="">John</Name>
      </xml>
    </Post>
  </s:Body>
</s:Envelope>}  System.ServiceModel.Channels.Message {System.ServiceModel.Channels.BufferedMessage}

(есть определение пространства имен по умолчанию с помощьюузел Name).

И после этого мой сервис работает нормально.

Мое предложение по причине проблемы :

На случай, есликогда я определил пустое пространство имен для события [XmlType(Namespace = "")]public class SomeEvent {...}, атрибут XmlType будет пропущен при генерации клиентского кода.И это помещает, когда запрос будет отправлен, XML, описывающий событие, помещается в пространство имен ServiceContract.После этого WCF не может десериализовать событие.

Таким образом, есть два решения проблемы :

  1. Избегайте использования события с пустым пространством имен (см.сценарий использования 2).
  2. Добавить частичный класс для события [XmlType(Namespace = "")]public partial class SomeEvent {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...