views:

289

answers:

4

I have an object that has a generic IList in it that is being returned from a WCF web service method:

[DataContract(Name = "PageableList_Of_{0}")]
public class PageableResults<T>
{
    [DataMember]
    public IList<T> Items { get; set; }
    [DataMember]
    public int TotalRows { get; set; }
}

[OperationContract]
PageableResults<ContentItem> ListCI();

When I call this method on the service it executes the entire method fine, but at the very end it throws a System.ExecutionEngineException without an InnerException. I've tried returning a concrete List<> object and that seems to work, but unfortunately I need to find a workaround to return an IList. Are there any attributes I need to put in to solve this?

+1  A: 

I don't think you can do this. How will the serializer know what to desearialize to? Lots of things could implement an IList, and an interface doesn't have a constructor.

Steve
It seems to work fine when using netTcpBinding, but not with WSHttpBinding
Nick
what is the underlying type it is deserializing to then? I don't see how this could work unless it is just randomly picking a container that implements IList and sticks them in there.
Steve
+1  A: 

It appears that this is a bug in WCF, which is fixed in .NET 4. However, there are several workarounds listed in this thread:
http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=433569

Summary:
- Put the assemblies that contain the DataContracts into the GAC.
- Set the LoaderOptimization to SingleDomain.

Mas
A: 

You'll have to add KnownTypes attribute on the class definition above your class definition for each usage of T. Like this:


[KnownType(typeof(ContentItem))]
[DataContract(Name = "PageableList_Of_{0}")]
public class PageableResults<T>
{
    [DataMember]
    public IList<T> Items { get; set; }
    [DataMember]
    public int TotalRows { get; set; }
}

[OperationContract]
PageableResults ListCI();

Alternatively you can define your own collection class, that has a TotalRows property, like this:


[KnownType(typeof(ContentItem))]
[DataContract(Name = "PageableList_Of_{0}")]
public class PageableResults<T> : EntityCollectionWorkaround<T>
{   
    [DataMember]
    public int TotalRows { get; set; }
}

Where EntityCollectionWorkaround is defined here:
http://borismod.blogspot.com/2009/06/v2-wcf-collectiondatacontract-and.html

Boris Modylevsky
A: 

Inherit from PageableResults to make a closed generic subclass, in your case PageableContentItem or something like that, and use that as return type. With webservices normally the xml serializer is used and it needs to know everything in advance, that's why you can't return interface types as well.

    public class PageableContentItem
        : PageableResults<ContentItem>
    {

    }

[OperationContract]
PageableContentItem ListCI();
BennyM