【问题标题】:WCF Client Exception: error while trying to deserialize parameterWCF 客户端异常:尝试反序列化参数时出错
【发布时间】:2014-05-16 20:08:30
【问题描述】:

我在尝试调用 WCF 服务时收到此错误:

格式化程序在尝试反序列化 消息:尝试反序列化参数时出错 http://tempuri.org/:ResultValue。 InnerException 消息是“错误” 在第 1 行位置 1741. 元素 'htp://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType' 包含映射到名称的类型的数据 'htp://schemas.datacontract.org/2004/07/DataAccess:Person'。 反序列化器不知道映射到此名称的任何类型。 考虑使用 DataContractResolver 或添加对应的类型 'Person' 到已知类型列表 - 例如,通过使用 KnownTypeAttribute 属性或通过将其添加到已知类型列表中 传递给 DataContractSerializer。'。

我有一个具有以下定义的接口项目:

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; }
}

我有一个实现接口的 DataAccess 项目:

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; }
    }
}

我的服务合同如下所示:

[ServiceContract]
[ServiceKnownType(typeof(Person))]
[ServiceKnownType(typeof(PersonExtended))]
public interface IMyService
{
    [OperationContract]
    ServiceCallResult<GetPeopleResponse> GetPeople(GetPeopleRequest request);
}

我的服务看起来像:

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;
    }
 }

我的响应对象看起来像:

[DataContract]
[KnownType(typeof(PersonExtended))]
[KnownType(typeof(Person))]
[KnownType(List<Person>))]
[KnownType(List<PersonExtended))]
public class GetPeopleResponse
{
    [DataMember]
    public List<PersonExtended> People { get; set; }
}

Response 对象只是包装在一个包含状态信息等的MessageContract 对象中。

编辑 如果我在整个工作流程中删除联系人(列表)属性,它工作正常。我想知道它是否与尝试使用带有接口列表而不是具体对象的属性有关,但我不确定如何在不添加循环引用的情况下通过我的项目结构解决这个问题。

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    你需要 [DataContract][DataMember] Person

    [DataContract]
    public class Person : IPerson
    {
        [DataMember]
        public string Name { get; set; }
    }
    

    KnownTypeAttribute 应该使您能够为给定的DataContract 指定可接受的派生类。它指定了在序列化反序列化给定类型时应该被DataContractSerializer识别的类型。

    GetPeopleResponse 不派生自 PersonPersonExtended...

    您的代码中还有很多对我来说根本没有意义的东西...... 这对我来说很有意义......

    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
        }
    }
    

    【讨论】:

    • 我认为还不够。我已经更新了我的问题。这代表了我的专有对象的简化版本。 ServiceCallResult 对象只是一个包含状态等信息的包装器。
    • 您的服务类末尾有一个 return 语句,告诉我您不知道自己在做什么......服务类也没有实现接口声明的功能。
    • 其实,我并不是不知道自己在做什么。这是一个简单的剪切/粘贴问题。我显然只是省略了函数def,它需要在那里满足接口。
    • 为什么在请求没有任何用途的情况下将其作为参数发送?您可以在界面中定义这样的函数以满足您的需求ServiceCallResult&lt;GetPeopleResponse&gt; GetPeople(); 并且看在上帝的份上,尝试在PeoplePeopleExtended 类上添加[DataContract][DataMember] 属性。
    • 同样,这是一个简化版本——请求参数通常包含过滤器信息等。我确实将DataContractDataMember 属性添加到DataAccess 类,但无济于事。如上面的编辑所示,如果我从扩展对象中删除作为List&lt;IPerson&gt;Contacts 属性,它可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 2020-03-16
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多