Reputation: 43
I am getting this error when I try to call a WCF Service:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:ResultValue. The InnerException message was 'Error in line 1 position 1741. Element 'htp://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType' contains data from a type that maps to the name 'htp://schemas.datacontract.org/2004/07/DataAccess:Person'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'Person' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'.
I have a Interfaces project with the following definitions:
public interface IPerson
{
string Name { get; set; }
}
public interface IPersonExtended : IPerson
{
// If I remove the List of IPerson property, it works fine
List<IPerson> Contacts { get; set; }
}
I have a DataAccess project that implements the interfaces:
public class Person : IPerson
{
public string Name { get; set; }
}
public class PersonExtended : IPersonExtended
{
public string Name { get; set; }
private List<IPerson> mContacts = new List<IPerson>();
// If I remove the List of IPerson property, it works fine
public List<IPerson> Contacts
{
get { return mContacts; }
set { mContacts = value; }
}
}
My Service Contract looks like this:
[ServiceContract]
[ServiceKnownType(typeof(Person))]
[ServiceKnownType(typeof(PersonExtended))]
public interface IMyService
{
[OperationContract]
ServiceCallResult<GetPeopleResponse> GetPeople(GetPeopleRequest request);
}
My Service looks like:
public class MyService : IMyService
{
public ServiceCallResult<GetPeopleResponse> GetPeople(GetPeopleRequest request)
{
GetPeopleResponse response = new GetPeopleResponse();
// Get Some people that have contacts
response.People = GetPeopleFromSomewhere();
ServiceCallResult<GetPeopleResponse> result =
new ServiceCallResponse<GetPeopleResponse> { ResultValue = response };
return result;
}
}
And my response object looks like:
[DataContract]
[KnownType(typeof(PersonExtended))]
[KnownType(typeof(Person))]
[KnownType(List<Person>))]
[KnownType(List<PersonExtended))]
public class GetPeopleResponse
{
[DataMember]
public List<PersonExtended> People { get; set; }
}
The Response object is just wrapped in a MessageContract
object that contains status information, etc.
EDIT If I remove the Contact (List) property through the entire workflow, it works fine. I'm wondering if it is related to trying to use a property with a list to an interface instead of a concrete object, but I'm not sure how to get around that with my project structure without adding a circular reference.
Upvotes: 4
Views: 13658
Reputation: 1977
you need [DataContract]
and [DataMember]
on the Person
class
[DataContract]
public class Person : IPerson
{
[DataMember]
public string Name { get; set; }
}
KnownTypeAttribute
is supposed to enable you to designate acceptable derived class for a given DataContract
. It specifies types that should be recognised by the DataContractSerializer
when Serializing or Deserializing a given type.
GetPeopleResponse
does not derive from Person
or PersonExtended
...
Also there is a lot of stuff in your code that doesn't make sense at all to me... Here is something that makes sense to me...
public interface IPerson {
string Name { get; set; }
}
public interface IPersonExtended : IPerson {
List<IPerson> Contacts { get; set; }
}
[DataContract]
public class Person : IPerson {
[DataMember]
public string Name { get; set; }
}
[DataContract]
public class PersonExtended : Person, IPersonExtended {
[DataMember]
public List<Person> Contacts { get; set; }
public PersonExtended() {
Contacts = new List<Person>();
}
}
[ServiceContract]
public interface IMyService {
[OperationContract]
IList<PersonExtended> GetAllPeople();
}
public class MyService : IMyService
{
private IList<PersonExtended> _people;
public MyService() {
_people = new IList<PersonExtended>();
}
public IList<PersonExtended> GetAllPeople() {
return _people
}
}
Upvotes: 2