Как использовать оба 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(который используется для детального контроля сообщений)