Reputation: 2146
Before you begin sorry for the length of this post...
Does anyone know why I can't pass an array of the class as a dynamic property through WCF ?
I have a ServiceOperationResponse class which is used to pass messages around my solution as shown below.
The message details datamember is a dynamic type allowing any object to be passed simply. This works fine under nearly all circumstances as I can set the ServiceKnownType for each of the WCF server interfaces.
However if I try to pass a ServiceOperationResponse object through WCF when the MessageDetails property is itself an array or list of type ServiceOperationResponse I get the following error:
The InnerException message was 'Error in line 1 position 576. Element 'http://schemas.datacontract.org/2004/07/Library:MessageDetails' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/Library:ArrayOfServiceOperationResponse'. The deserializer has no knowledge of any type that maps to this name.
This occurs when I have set the ServiceKnownType to any of the following, ServiceOperationResponse[], List.
Other types of lists or arrays can be passed with no problems, also if I create another property of type ServiceOperationResponse[], i.e. an array of responses, in the main ServiceOperationResponse and populate this instead then all data is properly deserialized. However I would prefer if at all possible not to have to add this property just for 1 particular case.
/// <summary>
/// Class used to pass details between services
/// </summary>
[DataContract]
public class ServiceOperationResponse
{
/// <summary>
/// the originating hostname or keyname
/// </summary>
[DataMember]
public string HostName { get; set; }
/// <summary>
/// the operation name
/// </summary>
public string OperationName { get; set; }
/// <summary>
/// the particular message details
/// </summary>
[DataMember]
public dynamic MessageDetails { get; set; }
}
shown below is some sample code that will trigger a failure if I try to pass back from WCF to a client
var responseList = new List<ServiceOperationResponse>();
for (int i = 0; i < 3; i++)
{
var responseElement = new ServiceOperationResponse()
{
HostName = Environment.MachineName,
MessageDetails = "this is a test"
};
responseList.Add(responseElement);
}
var response = new ServiceOperationResponse()
{
HostName = Environment.MachineName,
OperationName = "Get a list of service responses",
MessageDetails = responseList
};
Upvotes: 3
Views: 1646
Reputation: 3714
WCF uses the concept of contracts for communication. Contracts, among other things, specify the shape of the data that is being transmitted. That means that your operation contract has to have a well-defined shape; dynamic (or more accurately Object, as it is represented in metadata) does not have a well-defined shape.
You can get around that by adding the KnownTypeAttribute to your DataContract class, specifying the types of data that may be transmitted but are not explicitly included in the definitions of the contract class. But that will only work if you know ahead of time every possible type of every object that might be present in the dynamic property.
I would start by questioning why you have a dynamic property in a DataContract to begin with.
Upvotes: 1