How can I return interface types in generic type parameters from the OperationContracts in my WCF REST service? More specifically, it works for one operation but not when I add a second operation with a generic T that is an interface. 
I'm using JSON as the request and response format, feeding a non-WCF client that parses the JSON responses for the data it needs. I am not using SOAP, or the WSDL generated by the service.
My service interface:
[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(ServiceKnownTypesHelper))]
public interface IMyService
{
    [WebGet(UriTemplate="count")]
    [OperationContract]
    IServiceResult<int> GetCount();
    [WebGet(UriTemplate="desc")]
    [OperationContract]
    IServiceResult<string> GetDescription();
    [WebGet(UriTemplate="foo")]
    [OperationContract]
    IServiceResult<IFooData> GetFooData();
    // Fails when I invoke either method if I uncomment this operation.
    //[WebGet(UriTemplate="bar")]
    //[OperationContract]
    //IServiceResult<IBarData> GetBarData();
}
I left GetCount() and GetDescription() in the example to point out that those two generic results work fine, but obviously they are concrete types. And even GetFooData() works fine until I add a second method of IServiceResult<T> where T is an interface. 
The return types of GetFooData() and GetBarData() are not the same, nor are the concrete classes that implement them.
You may imagine that I've reduced the implementation to a skeleton as I don't think the implementation is the heart of the problem:
#region My service implementation
public class MyService : IMyService
{
    public IServiceResult<int> GetCount()
    {
        return new ServiceResult<int>(42);
    }
    public IServiceResult<string> GetDescription()
    {
        return new ServiceResult<string>("Muffins");
    }
    public IServiceResult<IFooData> GetFooData()
    {
        return new ServiceResult<IFooData>(new FooData() { Foo = 99 });
    }
    public IServiceResult<IBarData> GetBarData()
    {
        return new ServiceResult<IBarData>(new BarData() { Bar = "Elvis was here" });
    }
}
#endregion
#region ServiceKnownTypesHelper.GetServiceKnownTypes():
public static class ServiceKnownTypesHelper
{
    private static IList<Type> serviceKnownTypes = new List<Type>()
        {
            typeof(FooData),
            typeof(BarData),
            typeof(ServiceResult<int>),
            typeof(ServiceResult<string>),
            typeof(ServiceResult<IFooData>),
            typeof(ServiceResult<IBarData>),
        };
    public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider paramIgnored)
    {
        return serviceKnownTypes;
    }
}
#endregion
#region IServiceResult<T> and its concrete implementation:
public interface IServiceResult<T>
{
    IList<string> Errors { get; }
    T Value { get; set; }
}
[DataContract]
public class ServiceResult<T> : IServiceResult<T>
{
    public ServiceResult(T value)
    {
        this.Value = value;
    }
    private IList<string> errors = new List<string>();
    [DataMember]
    public IList<string> Errors
    {
        get
        {
            return this.errors;
        }
    }
    [DataMember]
    public T Value { get; set; }
}
#endregion
#region IFooData and its concrete implementation:
public interface IFooData
{
    int Foo { get; set; }
}
[DataContract]
public class FooData: IFooData
{
    [DataMember]
    public int Foo { get; set; }
}
#endregion
#region IBarData and its concrete implementation:
public interface IBarData
{
    string Bar { get; set; }
}
[DataContract]
public class BarData: IBarData
{
    [DataMember]
    public string Bar { get; set; }
}
#endregion
And the error message when I invoke GetBarData() from the browser:
Type 'ServiceResult`1[IBarData]' cannot be added to list of known types since another type 'ServiceResult`1[IFooData]' with the same data contract name 'http://schemas.datacontract.org/2004/07/ServiceResultOfanyType' is already present.
The rest of the error message is a red herring about colliding collection types List<Test> and Test[], which isn't the case here. 
Clearly, IFooData and IBarData aren't the same, nor are the classes that implement them. 
So why do ServiceResult<IFooData> and ServiceResult<IBarData> both resolve to ServiceResultOfanyType? 
Am I missing something, or is there no way to fix this?
After much trial and error, I've finally got this working with minimal changes:
ServiceResult<T> instead of IServiceResult<T>.  In fact, IServiceResult<T> is now gone entirely.GetServiceKnownTypes() no longer returns all the variants of ServiceResult<T>.  I only return the DataContracts used as T.
#region My service interface
[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(ServiceKnownTypesHelper))]
public interface IMyService
{
    [WebGet(UriTemplate="count")]
    [OperationContract]
    ServiceResult<int> GetCount();
    [WebGet(UriTemplate="desc")]
    [OperationContract]
    ServiceResult<string> GetDescription();
    [WebGet(UriTemplate="foo")]
    [OperationContract]
    ServiceResult<IFooData> GetFooData();
    [WebGet(UriTemplate="bar")]
    [OperationContract]
    ServiceResult<IBarData> GetBarData();
}
#endregion
#region My service implementation (minus bodies)
public class MyService : IMyService
{
    public ServiceResult<int> GetCount() {}
    public ServiceResult<string> GetDescription() {}
    public ServiceResult<IFooData> GetFooData() {}
    public ServiceResult<IBarData> GetBarData() {}
}
#endregion
#region ServiceKnownTypes
// My list of ServiceKnownTypes is now much shorter and simpler. I was feeding the service too much information
public static class ServiceKnownTypesHelper
{
    private static IList<Type> serviceKnownTypes = new List<Type>()
        {
            typeof(FooData),
            typeof(BarData),
            //typeof(ServiceResult<int>),
            //typeof(ServiceResult<string>),
            //typeof(ServiceResult<IFooData>),
            //typeof(ServiceResult<IBarData>),
        };
    // Remaining implementation is the same as before
}
#endregion
#region ServiceResult<T> with no interface (it's not used or needed)
[DataContract]
public class ServiceResult<T> //: IServiceResult<T>
{
    // implementation is the same as before
}
#endregion
I can now invoke all of those methods and get back lists of generic types referred to by their interfaces in the ServiceContract.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With