views:

21

answers:

0

Update:

I have found that the error is occurring in the System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.VerifyObjectCompatibilityWithInterface method.

If I switch the WebMessageFormat to XML then it works fine. Is this a bug in the JSON Serializer?

System.Runtime.Serialization.SerializationException occurred
Message="'HealthMEDX.Core.Home.TestCollection' is a collection type and cannot be serialized when assigned to an interface type that does not implement IEnumerable ('HealthMEDX.Core.Home.ITestCollection'.)"

Source="System.ServiceModel.Web"

StackTrace: at 
System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.VerifyObjectCompatibilityWithInterface(DataContract contract, Object graph, Type declaredType)

InnerException: 

I have am having an issue when attempting to return JSON data from a WCF Service. I have tracked the issue down to the ResponseFormat:=WebMessageFormat.JSON, but I am unable to make any further progress.

I am wanting the return types of my service to be an interface so that I have a little more control over the responses that are coming to my application.

I know that returning an interface requires the ServiceKnownType and requires KnowsType on the objects so that they can serialize properly. I have an example working, however, when add a property with a class that inherits from iList things go bad. The service returns nothing. I have confirmed via Fiddler that the content-length of the response is 0. However if I switch the ResponseFormat to WebMessageFormat.XML it works fine and all objects are returned. I have included as much code (and probably more) as I think is necessary. If something else is needed, let me know.

Any insight is greatly appreciated.

Code Notes:

If you comment out the DataMember Attribute on the Values property in TestResult class you will see that the code works perfectly when returning JSON.

If you change the return Type of the Values Property to be TestCollection instead of ITestCollection it works as well.

Andy S.

Service Interface

<ServiceContract()> _
Public Interface IPortalCoreService
    <OperationContract()> _
    <WebGet(UriTemplate:="GetTest", ResponseFormat:=WebMessageFormat.Json, BodyStyle:=WebMessageBodyStyle.Bare)> _
     <ServiceKnownType(GetType(TestResult))> _
    Function GetTest() As ITestResult
End Interface

Service Class

Public Class PortalCoreService
    Implements IPortalCoreService

    Public Function GetTest() As ITestResult Implements IPortalCoreService.GetTest
        Dim retVal As ITestResult = New TestResult
        Return retVal
    End Function
End Class

Interfaces

Public Interface ITestCollection
    Inherits IList(Of ITest)
End Interface

Public Interface ITest
    Property A() As String
End Interface

Public Interface ITestResult
    Property Values() As ITestCollection
    Property Values1() As IList(Of ITest)
    Property T() As ITest
End Interface

Classes

Public Class TestCollection
    Inherits List(Of ITest)
    Implements ITestCollection
End Class

<DataContract()> _
Public Class Test
    Implements ITest

    <DataMember()> _
    Public Property A() As String Implements ITest.A
        Get
            Return "A"
        End Get
        Set(ByVal value As String)
        End Set
    End Property
End Class


<DataContract(), KnownType(GetType(Test)), KnownType(GetType(TestCollection))> _
Public Class TestResult
    Implements ITestResult
    Private _values As TestCollection
    Public Sub New()
        _values = New TestCollection()
        For i = 0 To 3
            _values.Add(New Test)
        Next
    End Sub

    <DataMember()> _
    Public Property TestObj() As ITest Implements ITestResult.T
        Get
            Return New Test()
        End Get
        Set(ByVal value As ITest)
        End Set
    End Property

    <DataMember()> _
    Public Property Values() As ITestCollection Implements ITestResult.Values
        Get
            Return _values
        End Get
        Set(ByVal value As ITestCollection)
        End Set
    End Property


    <DataMember()> _
    Public Property Values1() As IList(Of ITest) Implements ITestResult.Values1
        Get
            Return _values
        End Get
        Set(ByVal value As IList(Of ITest))
        End Set
    End Property
End Class