The use of type 'Microsoft.Xrm.Sdk.Query.FilterExpression' as a get-only collection is not supported with NetDataContractSerializer.

A while back I had a problem with calling the CRM2011 WCF endpoint where the Microsoft SDK Proxy assembly was not available (e.g. Silverlight). When calling RetrieveMultiple I was getting the following exception:

"The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://schemas.microsoft.com/xrm/2011/Contracts/Services:request. The InnerException message was 'The use of type 'Microsoft.Xrm.Sdk.Query.FilterExpression' as a get-only collection is not supported with NetDataContractSerializer.Consider marking the type with the CollectionDataContractAttribute attribute or the SerializableAttribute attribute or adding a setter to the property."

The strange thing was that this appeared even when not using a FilterExpression in the query. After a bit of digging it turned out to be to do with the serialization of the ColumnSet object when AllColumns was set to true, but the Columns collection was empty.

The solution was to use partial classes to simulate the Microsoft SDK Proxy classes, and then set the Columns collection to a 'dummy' value when AllColumns was set to true.

partial class ColumnSet
{
    public ColumnSet()
    {
      this.ColumnsField = new ObservableCollection();
    }
    public ColumnSet(params string[] columns)
    {
      this.Columns = new ObservableCollection(columns);
    }
    public ColumnSet(bool allColumns)
    {
      this.AllColumnsField = allColumns;
      this.ColumnsField = new string[] { allColumns.ToString() };
    }
}

Then you can use:

query.ColumnSet = new ColumnSet("col1","col2","col3");

 

or

query.ColumnSet = new ColumnSet(true);

If you are not using the ObservableCollection in your proxy classes, use this version instead:

partial class ColumnSet
  {
    public ColumnSet()
    {
      this.ColumnsField = new ObservableCollection();
    }
    public ColumnSet(params string[] columns)
    {
      this.Columns = columns;
    }
    public ColumnSet(bool allColumns)
    {
      this.AllColumnsField = allColumns;
      this.ColumnsField = new string[] { allColumns.ToString() };
    }
  }

Hope this helps!

Comments are closed