0

I have the following code for a web service:

[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);
        }
    }
}

The service accepts the following SOAP Request:

<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>

However, it should accept the following SOAP Request (Without the "CustomStrings"-tag):

<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>

If I don't use MessageContract, like this:

[OperationContract]
WrapperResponse GetStringCollection(StringCollection CustomRequest);

I am able to achieve the following XML, which is close to what I want:

<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>

But the "GetStringCollection"-tag is present, which is what MessageContract helps me remove.

So I need both the MessageContract and the CollectionDataContract, but if I do the following:

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

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

I get an exception:

"Exception Details: System.InvalidOperationException: The type WcfService1.StringCollection defines a MessageContract but also derives from a type System.Collections.Generic.List`1[System.String] that does not define a MessageContract. ÿAll of the objects in the inheritance hierarchy of WcfService1.StringCollection must defines a MessageContract."

So the question is: Is there a way to use both the MessageContract and CollectionDataContract in the top class? If not, how can I then accept the wanted request?

H H
  • 263,252
  • 30
  • 330
  • 514
Godspark
  • 354
  • 2
  • 13

1 Answers1

0

Message Contract IS NOT a DataContract or CollectionDataContract! See DataContract-Vs-MessageContract-in-WCF on codeproject

You can say, that you want to declare a contract for transfering data between consumer and provider. This contract can be CollectionDataContract(List) OR DataContract(class) OR MessageContract(which used for detailed message control)

Vladislav
  • 218
  • 1
  • 13
  • So how can I achieve the desired request? – Godspark Sep 28 '16 at 07:16
  • @Godspark, You need to use only CollectionDataContract and use it in your OperationContract. Just remove [MessageContract] attribute. – Vladislav Sep 28 '16 at 07:20
  • But then I end up with the third request from the question, which contains the extra "" tag-pair. How can I avoid that, without using MessageContract? – Godspark Sep 28 '16 at 07:36