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