Tuesday, April 12, 2011

LINQ and WCF

I am sure that for most of you this will be back to the basics but I had this exception yesterday:

Type 'System.Linq.Enumerable+WhereSelectEnumerableIterator`2[ClassA,ServiceClassA]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  See the Microsoft .NET Framework documentation for other supported types.

That I couldn’t find a solution for in Google, though I solved it fairly easily.

 

The situation was this I had a service lets just call it ClassService with this method:

  1. [ServiceContract]
  2. public interface IClassService
  3. {
  4.     void SomeMethod(ServiceEntity entity);
  5. }

ServiceEntity was defined as:

  1. [DataContract]
  2. public class ServiceEntity
  3. {
  4.     [DataMember]
  5.     public IEnumerable<ServiceClassA> As { get; set; }
  6. }
  7.  
  8. [DataContract]
  9. public class ServiceClassA { }

 

Now the client looked something like:

  1. public IClassService ClassService { get; set; }
  2.  
  3. public void CallService(IEnumerable<ClassA> list)
  4. {
  5.     ClassService.SomeMethod(new ServiceEntity{As = list.Select(Convert)});
  6. }
  7.  
  8. private ServiceClassA Convert(ClassA a)
  9. {
  10.     return new ServiceClassA();
  11. }

(just imagine the constructor initializing the ClassService)

Do you see the mistake?

The problem comes from the line:

  1. ClassService.SomeMethod(new ServiceEntity{As = list.Select(Convert)});

Or most specifically:

  1. new ServiceEntity{As = list.Select(Convert)}

The problem is that LINQ doesn’t actually executes this query. It wait until you try to do something with it like converting it to a list or try using one of the entities. The IEnumrable actually has the type of 'System.Linq.Enumerable+WhereSelectEnumerableIterator`2[ClassA,ServiceClassA]' which is not a WCF DataCotract.

 

The solution is fairly easy:

  1. ClassService.SomeMethod(new ServiceEntity{As = list.Select(Convert).ToList()});

Just use the LINQ query by creating a List out of it is enough.

 

Keywords: LINQ, WCF, Exception

IceRocket Tags: ,,