Как использовать оба MessageContract и CollectionDataContract в одном классе?

У меня есть следующий код для веб-службы:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    WrapperResponse GetStringCollection(CustomRequest req);
}

[MessageContract(WrapperNamespace = Constants.NamespaceTem)]
public class CustomRequest
{
    [MessageBodyMember]
    public StringCollection CustomStrings
    {
        get; set;
    }
}

[CollectionDataContract(ItemName = "CustomString")]
public class StringCollection : List<string>
{
    public StringCollection(): base() { }

    public StringCollection(string[] items) : base()
    {
        foreach (string item in items)
        {
            Add(item);
        }
    }
}

Сервис принимает следующий SOAP-запрос:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">      
  <s:Body>
    <CustomRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="CustomNamespace">
      <CustomStrings xmlns:d4p1="http://schemas.datacontract.org/2004/07/WcfService1">
        <d4p1:CustomString>text1</d4p1:CustomString>
        <d4p1:CustomString>text2</d4p1:CustomString>
      </CustomStrings>
    </CustomRequest>
  </s:Body>
</s:Envelope>

Однако он должен принять следующий запрос SOAP (без тега "CustomStrings"):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">      
  <s:Body>
    <CustomRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="CustomNamespace">
      <d4p1:CustomString>text1</d4p1:CustomString>
      <d4p1:CustomString>text2</d4p1:CustomString>
    </CustomRequest>
  </s:Body>
</s:Envelope>

Если я не использую MessageContract, вот так:

[OperationContract]
WrapperResponse GetStringCollection(StringCollection CustomRequest);

Я могу добиться следующего XML, который близок к тому, что я хочу:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetStringCollection xmlns="CustomNamespace">
      <CustomRequest xmlns:d4p1="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <d4p1:CustomString>text1</d4p1:CustomString>
        <d4p1:CustomString>text2</d4p1:CustomString>
      </CustomRequest>
    </GetStringCollection>
  </s:Body>
</s:Envelope>

Но присутствует тег GetStringCollection, который MessageContract помогает мне удалить.

Поэтому мне нужны и MessageContract, и CollectionDataContract, но если я сделаю следующее:

[MessageContract]
[CollectionDataContract(ItemName = "CustomString")]
public class StringCollection : List<string>
{
    public StringCollection(): base() { }

    public StringCollection(string[] items) : base()
    {
        foreach (string item in items)
        {
            Add(item);
        }
    }
}

Я получаю исключение:

"Сведения об исключении: System.InvalidOperationException: тип WcfService1.StringCollection определяет MessageContract, но также является производным от типа System.Collections.Generic.List`1[System.String], который не определяет MessageContract. Ll Все объекты в наследовании. Иерархия WcfService1.StringCollection должна определять MessageContract. "

Таким образом, вопрос: есть ли способ использовать оба MessageContract и CollectionDataContract в верхнем классе? Если нет, то как я могу принять запрос?

1 ответ

Контракт сообщения НЕ ЯВЛЯЕТСЯ DataContract или CollectionDataContract! См. DataContract-Vs-MessageContract-in-WCF для проекта кода

Можно сказать, что вы хотите объявить договор на передачу данных между потребителем и поставщиком. Этот контракт может быть CollectionDataContract(List) ИЛИ DataContract (класс) ИЛИ MessageContract(который используется для детального контроля сообщений)

Другие вопросы по тегам