RiddlerDev
RiddlerDev

Reputation: 7469

WCF - Generic List (of T)

I have a list of a custom DTO that I am trying to pass across to a WCF service.

I am getting the following error:

There was an error while trying to serialize parameter tcp://localhost/:oObject. The InnerException message was 'Type 'System.Collections.Generic.List`1[[TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat.HeartBeatDTO, WFCommon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ArrayOfHeartBeatDTO:TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

I have the DTO DataContract and DataMember set. I did an auto WCF service reference, and made sure to do advanced options to change collections to be generic lists instead of array.

What am I missing? Been through a lot of sites that do similar things, but cannot get mine to work past this error. Any ideas?

Code from sender:

<DataContract(Name:="HeartBeatDTO", Namespace:="TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat")> _
Public Class HeartBeatDTO

Public Sub IssuePatientReport()
  SBClient.SendCommunication(_PatientID, _HeartBeats)
End Sub

Code at receiver:

Public Sub SendCommunication(ByVal sKey As String, ByVal oObject As Object) Implements iOperatorCommunication.SendCommunication
        If _CurrentCommunicationLog.ContainsKey(sKey) Then
            _CurrentCommunicationLog.Item(sKey) = oObject
        Else
            _CurrentCommunicationLog.Add(sKey, oObject)
        End If
    End Sub

My interface:

<ServiceContract(Namespace:="tcp://localhost/")> _
<ServiceKnownType(GetType(List(Of HeartBeatDTO)))> _
Public Interface iOperatorCommunication
    <OperationContract()> _
    Function ReceiveCommunication(ByVal sKey As String) As Object

    <OperationContract()> _
    Function ReturnCommunicationLevel() As Integer

    <OperationContract()> _
    Function ReturnCommunications() As Dictionary(Of String, Object)

    <OperationContract()> _
    Function ReturnCommunicationsByKeySearch(ByVal sSearch As String) As Dictionary(Of String, Object)

    <OperationContract()> _
    Sub SendCommunication(ByVal sKey As String, ByVal oObject As Object)
End Interface

UPDATE: Here is the new error message:

There was an error while trying to serialize parameter tcp://localhost/:oObject. The InnerException message was 'Type 'TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat.HeartBeatDTOList' with data contract name 'HeartBeatDTOList:TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

Upvotes: 1

Views: 5593

Answers (1)

marc_s
marc_s

Reputation: 755321

If you have custom collection types, you might need to decorate those with a special attribute - see the MSDN docs on CollectionDataContract:

[CollectionDataContract] 
public class CustomerList2 : Collection<string> {}

Could that be the problem?


UPDATE: ok, thanks for the posting the interface. I'm no VB.NET expert, but from what I understand and see, you're never actually using the "HeartbeatDTO" type in any of your methods decorated with a OperationContract attribute - right?

So I would imagine you probably also have to define that as a "ServiceKnownType" - try this:

<ServiceContract(Namespace:="tcp://localhost/")> _
<ServiceKnownType(GetType(HeartBeatDTO))> _
<ServiceKnownType(GetType(List(Of HeartBeatDTO)))> _
Public Interface iOperatorCommunication

Does that help?

Also: is there any particular reason you're using "Object" as type throughout your service contract? Couldn't you specify either HeartbeatDTO or List(Of HeartbeatDTO)?

UPDATE: could you possibly try - just for the sake of seeing if it works - to create a new service interface list this:

<ServiceContract(Namespace:="tcp://localhost/")> _
Public Interface iOperatorCommunicationStripped
    <OperationContract()> _
    Sub SendCommunication(ByVal sKey As String, ByVal oObject As List(Of HeartbeatDTO))
End Interface

In this case, your service operation is explicit about its data type and uses a list of HeartbeatDTO objects which are defined as data contracts. If you know create a client proxy for this service contract and call the method - does this work??

Marc

Upvotes: 6

Related Questions