Почему WCF переносит типы запросов / ответов в другой элемент XML и как это предотвратить? - PullRequest
5 голосов
/ 15 июля 2009

У меня есть простой эхо-сервис, в котором я определил один метод операции и пару типов для запроса / ответа:

[ServiceContract(Name = "EchoService", 
                 Namespace = "http://example.com/services", 
                 SessionMode = SessionMode.NotAllowed)]
public interface IEchoService
{
    [OperationContract(IsOneWay = false,
                       Action = "http://example.com/services/EchoService/Echo", 
                       ReplyAction = "http://example.com/services/EchoService/EchoResponse")]
    EchoResponse Echo(EchoRequest value);
}

Типы данных:

[Serializable]
[DataContract(Namespace = "http://example.com/services/EchoService", 
              Name = "EchoRequest")]
public class EchoRequest
{
    public EchoRequest() { }

    public EchoRequest(String value)
    {
        Value = value;
    }

    [DataMember]
    public String Value { get; set; }
}

[Serializable]
[DataContract(Namespace = "http://example.com/services/EchoService", 
              Name = "EchoResponse")]
public class EchoResponse
{
    public EchoResponse() { }

    public EchoResponse(String value)
    {
        Value = value;
    }

    [DataMember]
    public String Value { get; set; }
}

Вызов Message.CreateMessage () для экземпляра EchoRequest дает:

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header />
    <s:Body>
      <EchoRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.com/services/EchoService">
        <Value>hello, world!</Value>
      </EchoRequest>
    </s:Body>
  </s:Envelope>

... это именно то, что я хочу. Однако, похоже, что служба ожидает, что тело сообщения будет дополнительно обернуто в другой элемент XML, например:

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header />
    <s:Body>
      <Echo xmlns="http://example.com/services">
        <EchoRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.com/services/EchoService">
          <Value>hello, world!</Value>
        </EchoRequest>
      </Echo>
    </s:Body>
  </s:Envelope>

UPDATE: Благодаря ответу Марка я изучил MessageContract вместо DataContract для типов запросов / ответов. Кажется, это ближе к тому, что я хочу, но теперь оно заходит слишком далеко и не ожидает внешнего элемента типа "EchoRequest".

Это сбивает с толку, поскольку каким-то образом Message.CreateMessage, по-видимому, неизменно генерирует правильный XML, поэтому, очевидно, он использует некоторую сериализацию по умолчанию, которую я хотел бы настроить для приема службы. Я просто неправильно понимаю, как работает Message.CreateMessage?

Ответы [ 2 ]

2 голосов
/ 15 июля 2009

IIRC, WCF по умолчанию использует стиль сообщения «Wrapped». Если вы хотите иметь возможность управлять тем, как сообщения сериализуются, вы можете определить явные сообщения, добавив MessageContractAttribute . С явными контрактами сообщений вы можете установить для свойства IsWrapped значение false.

В вашем случае я считаю, что EchoRequest и EchoResponse вообще не должны быть DataContracts, а скорее MessageContracts. Они очень похожи на MessageContracts для меня.

1 голос
/ 01 декабря 2012

Я в конечном итоге переключился на использование Контрактов сообщений с использованием TypedMessageConverter , с которым меня познакомили через ответ этого вопроса . Это был недостающий кусок здесь.

...