Here’s an interesting problem I encountered recently with a WCF based web service and the humble IList<T> interface.

I’m working on a classic 3-teir system: Client/Application/Database. The Client and Application are using Windows Communication Foundation (WCF) to interact. For convenience, we have an assembly of Data Transfer Objects (or DTOs) which is shared across both the client and the server.

While working on a recent system enhancement, I encountered an odd error - a NotSupportedException with the message “Collection was of a fixed size”.

The exception was thrown from this line of code:

fullReturn.Responses.Add(response);

Given that Responses is typed as an IList<Response>, this error didn’t make a lot of sense to me.

Turns out that the culprit is the serialisation technique used by WCF. When the property is of type IList<T> the content is handled as an array - specifically a Response[]!! While Arrays implement the interface, they don’t do so properly, throwing exceptions when you try to Add/Remove items:

In the .NET Framework version 2.0, the Array class implements the System.Collections.Generic.IList generic interface. ... when you cast an array to one of these interfaces is that members which add, insert, or remove elements throw NotSupportedException. -- http://msdn.microsoft.com/en-us/library/system.array.aspx

Fixing the problem involved two steps - changing the serializer and converting the data.

By default (if you make no choice), the serializer used by WCF works by sending the private member variables of the object. When deserialized, the private members are set directly, bypassing all of your own code on the object. The DataContract serializer works by sending the public properties of the object, and uses the property set methods to write the information into the object when deserialized.

In my case, I needed to switch to the DataContract serializer so that I could easily get my code into the flow to convert the data received. Adding the necessary DataContract and DataMember attributes onto the DTO was straightforward. Next, I converted my Responses property from an auto-property into one with a backing field and some conversion code for the inbound value in the set method.

[DataMember]
public IList<Response> Responses
{
    get { return mResponses; }
    set { mResponses = new List<Response>(value);
}

private List<Response> mResponses;

Now, it doesn’t matter that the serializer chooses to use a Response[] to send the data across the wire - the array is converted into the required list automatically on reception.

Comments

blog comments powered by Disqus
Next Post
Vending Machine UX Fail  30 May 2010
Prior Post
Specialist Classes  22 May 2010
Related Posts
A better approach to reflection  13 Oct 2018
Avoiding Magic Strings  06 Oct 2018
Capturing Validation Metadata  29 Sep 2018
Modelling Validation Metadata  22 Sep 2018
Validation Metadata  15 Sep 2018
Extending validation with warnings  08 Sep 2018
Validation recap  25 Aug 2018
Equality of validation  18 Aug 2018
Short-circuiting validation  11 Aug 2018
Aggregation of validation  04 Aug 2018
More csharp posts »
Archives
May 2010
2010