WCF OperationContract - which generic collection type should I expose?

Klaus Byskov Pedersen picture Klaus Byskov Pedersen · Feb 19, 2010 · Viewed 14.6k times · Source

I have a WCF web service that has a method that returns a generic collection. Now, my question is: Should I expose it as ICollection<T>, List<T>, IList<T>, IEnumerable<T> or something else?

I suppose that List<T> is out of the question since I want to avoid CA1002 errors, but the underlying type will be a List<T>.

I am really interested in hearing your takes on this, preferably with a good explanation of why you think what you think.

Thanks in advance

Answer

Aaronaught picture Aaronaught · Feb 19, 2010

Keep in mind that errors such as CA1002 are really meant to apply to libraries. A WCF service is not a library, it's an endpoint that's serializing everything over SOAP, REST, etc.

You'll find that if you try to expose an interface such as ICollection<T> or IList<T>, you'll get errors that the type can't be serialized. In fact, List<T> is probably the best choice here. When a proxy gets generated on the client side, it ends up as an array by default, and many if not most people change it to a List<T>, so 90% of the time, no matter how you choose to expose it, that's the type that the client is going to see anyway.

I'll note that it's generally good practice not to "return" a collection at all from a WCF operation or a web service in general. It's more common to create a proxy class that contains the collection you want, and return that, i.e.:

[OperationContract]
OrdersResult GetOrders(OrderRequest request);

Where the proxy class might look like this:

[DataContract]
public class OrdersResult
{
    [DataMember]
    public List<Order> Orders { get; set; }
}

That way if you decide you need to add more data to either the request or the response, you can do so without causing breaking changes to the client.


Addendum: The real issue here with WCF is that WCF doesn't know that a particular type is used only for outbound data. When any class is exposed through a WCF service, WCF assumes that it can be part of either a request or a response, and if it is part of a request, then the type must be concrete and cannot be immutable. That's the reason for all the other silly restrictions like requiring property setters.

You simply have no choice here but to use a concrete, mutable collection type, and in most cases that means either an array or a generic list.