我有DataContract类,它具有类型List<AnotherObject>
的属性。 AnotherObject也标有DataContract。出于某种原因,这个属性来自wcf服务为null,尽管我在服务器上填充它。这是设计的吗?
你走了。类定义:
[DataContract]
public class UserInfo
{
[DataMember]
public decimal UserID
{
get;
protected internal set;
}
[DataMember]
public string UserName
{
get;
protected internal set;
}
[DataMember]
public string Pswd
{
get;
protected internal set;
}
[DataMember]
public List<decimal> RoleID
{
get;
protected internal set;
}
List<UserRole> userRolesTable = new List<UserRole>();
[DataMember]
public List<UserRole> UserRoles
{
get
{
return userRolesTable;
}
protected internal set { }
}
}
[DataContract]
public class UserRole
{
[DataMember]
public decimal ROLEID { get; internal set; }
[DataMember]
public string ROLE_CODE { get; internal set; }
[DataMember]
public string ROLE_DESCRIPTION { get; internal set; }
[DataMember]
public decimal FORMID { get; internal set; }
[DataMember]
public string FORMCODE { get; internal set; }
[DataMember]
public string FORMNAME { get; internal set; }
}
UserRoles属性为null。
答案 0 :(得分:3)
为什么要让RoleId属性自动实现而不是UserRoles?代码按原样不起作用,因为你有一个空的setter。你应该只为它使用一个自动属性:
[DataMember]
public List<UserRole> UserRoles
{
get; set;
}
或者至少提供一个有意义的二传手。你的setter什么都不做,因此反序列化器无法填充该值。
答案 1 :(得分:1)
List<UserRole> userRolesTable = new List<UserRole>();
[DataMember]
public List<UserRole> UserRoles
{
get
{
return userRolesTable;
}
protected internal set { }
}
你的二传手是空的。放一些
userRolesTable = value;
另一方面,您的DataContract属性应该有 public setter。
答案 2 :(得分:1)
UserRoles属性上的Setter设置为internal。因为WCF框架将设置属性,所以它放弃了赋值,因为它被列为内部。
您可以使用该属性上的InternalsVisibleToAttribute属性执行此链接建议的内容,但我从未使用过它。
更新 我想说的是我打赌序列化工作正常,WCF框架无法将反序列化的值插入到主机代码中,因为根据数据契约,属性的内部Setter部分是不可访问的。使用InternalVisibleTo属性通知WCF序列化框架访问数据协定对象的客户端版本的setter。
答案 3 :(得分:0)
您需要实施setter ...
protected internal set { userRolesTable = value; }
答案 4 :(得分:0)
基本上,它是一个序列化问题。我过去在代码中遇到过这个问题,但已经有一段时间了,所以请耐心等待。
首先,我们需要在WCF调用之前找出对象关系是否为null,因此请在之前和之后进行调试。
如果在调用之前将对象返回为null,则有几个选项:
您可以在DbContext上显式使用.Include(“AnotherObject”)来获取对象。我通过让我的Read方法获取一个字符串数组来使用它,我过去常常包含所有必需的对象。这比自动获取所有对象更理想,因为在序列化期间,如果你采取一切措施,你可以很容易地将整个数据库序列化,这会引入性能和安全问题等等。
另一种选择是通过在列表前面添加关键字virtual来使用动态代理。但是,DataContractSerializer在序列化动态代理时遇到问题,因此您需要实现一个使用ProxyDataContractResolver而不是DataContractResolver的属性。此属性需要应用于可以传递动态代理的所有OperationContracts。这将自动获取所有对象引用,这可能是错误的编码实践,所以我建议使用上面的方法。
public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
{
public ApplyDataContractResolverAttribute() { }
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { }
public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
{
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
}
public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
}
public void Validate(OperationDescription description) { }
}
编辑:另外我认为你可以让数据合同中的setter不公开,因为我这样做并且它工作正常:)。但我会尝试先让你的setter公开,然后解决问题,然后恢复到受保护的setter,这样你就可以尽可能少地处理变量。