The Cheez Inside
The Cheez Inside

Reputation: 43

WCF Client Exception: error while trying to deserialize parameter

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

Answers (1)

furier
furier

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

Related Questions