1

Here's what I am trying to do. I have a WCF restful service, and I need to serialize multiple objects that inherit from the same class.

There is nothing in any of the base classes that needs to be serialized.

Here is a minimal demo that shows what I want to get to work:

<DataContract()>
Public Class BaseObj

    <DataMember()>
    Public ID As Integer

    Public Sub New(ByVal idval As Integer)
        ID = idval
    End Sub

End Class

<DataContract()>
Public Class TestObj1
    Inherits BaseObj

    Public Sub New(ByVal id As Integer)
        MyBase.New(id)
    End Sub

End Class

' Different from TestObj1 in real life
<DataContract()>
Public Class TestObj2
    Inherits BaseObj

    Public Sub New(ByVal id As Integer)
        MyBase.New(id)
    End Sub

End Class

And here's the code that uses it:

<ServiceContract()>
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerCall)>
Public Class Service1

    <WebGet(ResponseFormat:=WebMessageFormat.Json, UriTemplate:="Test?reqReportID={reqReportID}")>
    Public Function GetCollection(ByVal reqReportID As Integer) As List(Of BaseObj)

        Dim myObjs As New List(Of BaseObj)
        myObjs.Add(New TestObj1(20))
        myObjs.Add(New TestObj2(20))
        Return myObjs

    End Function

End Class

If I declare the List to be a list of TestObj1 instead, everything works.

Am I missing some crucial concept here?

EDIT:

The problem gains a new level of confusion by looking at this code:

    <WebGet(ResponseFormat:=WebMessageFormat.Json, UriTemplate:="Test?reqReportID={reqReportID}")>
    Public Function GetCollection(ByVal reqReportID As Integer) As BaseObj()

        Dim myObjs As New List(Of BaseObj)
        myObjs.Add(New TestObj1(20))
        myObjs.Add(New TestObj2(20))

        '   This guy works. Yields correct result of [{"ID":20},{"ID":20}] )
        Dim testStr As String = New JavaScriptSerializer().Serialize(myObjs.ToArray())

        '   But this guy still has problems...
        Return myObjs.ToArray()

    End Function

1 Answer 1

1

What you are missing is a [KnownType] attribute.

WCF requires a way of knowing all possible types so that it could publish the WSDL.

Have a look here.

UPDATE

The problem is that List<T> is not covariant.

Use IEnumerable<T> instead.

Sign up to request clarification or add additional context in comments.

6 Comments

Not a bad suggestion, but if I change the line <DataContract()> to <DataContract(),KnownType(GetType(BaseObj))> for both TestObj1 and TestObj2, the behavior remains unchanged. Is the problem that I am adding that wrong?
Sorry I have updated my answer. I noticed you did not need KnownType
@Aliostad, I really appreciate your input, however I'm still not getting it to work. I changed the return type to a simple array and it still has the same behavior. To make things more confusing, I can manually serialize the array it works just fine (see edits to question).
Array is not always covariant as well. I have updated my answer.Use IEnumerable<T> and that should work.
@Aliostad, I'm not sure that's explaining the reason, because manually serializing it does work. Changing the return type to IEnumerable(Of BaseObj) did not seem to change the behavior at all.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.