6
votes

I have a simple class:

[DataContract]
public class Book
{
    [DataMember]
    public Int32 ID { get; set; }

    [DataMember]
    public Nullable<Int32> AuthorID { get; set; }     
}

Which is retrieved via a WCF Service like:

public class BookService : IBookService
    {
        IService _service;

        public BookService()
        {
            _service = new BookService();
        }

        public IEnumerable<Book> GetBooks()
        {
            var Books = _service.GetBooks();
            return Books;
        }                
    }

I now want to extend this to include an additional function that would allow a LINQ query to include additional properties on the Book class (not shown in the cut down example above). The function for this (which works when included and called from within an MVC app) is:

    public IEnumerable<Book> GetBooks(params Expression<Func<Book, object>>[] includes)
    {
        var Books = _service.GetBooks(Expression<Func<Book, object>>[]>(includes));
        return Books;
    }

However, when ran from an WCF Service this generates an error as it can't be serialized:

System.ServiceModel.Description.DataContractSerializerOperationBehavior contract: http://tempuri.org/:IBookService ----> System.Runtime.Serialization.InvalidDataContractException: Type 'System.Linq.Expressions.Expression1[System.Func2[Foo.Book,System.Object]]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute.

I added the DataContract/DataMember attributes to the class so that it could be serialized, however I'm not sure what I need to do to allow the function parameter to be serialized.

Anyone have ideas on what I can do to allow this function to be used in the WCF service?

2
You will probably need to serialize the string representing the expression and parse the string back to an expression when you deserialize.Matt Burland
@Matt - You mean something like: "public IEnumerable<Book> GetBooks(string includesSerialized)" and force the calling application to create the serialized string before calling the function?ca8msm
it sounds like you're interested in a kind of odata protocol. try to use it insteadIgor Gnedysh
You probably need this library: github.com/esskar/Serialize.LinqEvk

2 Answers

0
votes

Could it maybe have something to do with the use of Expression?:

Why would you use Expression<Func<T>> rather than Func<T>?

0
votes

generic list like array are not Serializable, so that is why are you getting the error. Change your code so that you are passing the list of fields you want to return is in an object that can be serialized. Once you are passing parameters in an object that can be serialized you function should work when in web services.

[Data Contract] 
public class Field
{
   [DataMember]
   public string FieldName {get; set;}
}

Then you can pass it to the functions

List<Fields> fieldList = new List<Field>();
fieldList.Add(new Field("Field1");
fieldList.Add(new Field("Field2");
_service.GetBooks(Expression<Func<Book, object>>[]>(fieldList));

** Not sure of syntax of the last line, I have not work with expressions a lot