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
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
When are you done?  18 Apr 2022
Fixing GitHub Authentication  28 Nov 2021
Archives
May 2010
2010