Wcf newbie question: arrays as properties

I have a DataContract class that has a property of type List<AnotherObject> . AnotherObject is also marked with a DataContract. For some reason, this property comes from the wcf service as null, although I populate it on the server. Is it for design?

Here you go. Class Definitions:

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

The UserRoles property is null.

+4
source share
5 answers

Why do you allow automatic implementation of the RoleId property, but not UserRoles? The as-is code will not work because you have an empty setter. You should probably just use the auto-property for this:

 [DataMember] public List<UserRole> UserRoles { get; set; } 

Or at least provide a meaningful setter. You setter does nothing, so the de-serializer cannot fill in the value.

+3
source
 List<UserRole> userRolesTable = new List<UserRole>(); [DataMember] public List<UserRole> UserRoles { get { return userRolesTable; } protected internal set { } } 

Your setter is empty. Put some

 userRolesTable = value; 

Other, your DataContract properties must have public setters.

+1
source

Your setter has an internal property set in the UserRoles property. Because WCF will set the property, it refuses to assign a value because it is specified as internal.

http://connect.microsoft.com/data/feedback/details/625985/wcf-client-entities-with-internal-setters-and-internalsvisibletoattribute-on-asmbly-fail

You can do what this link offers using the InternalsVisibleToAttribute attribute for this property, but I never used it.

update I'm trying to say that I am sure that Serialization is working fine, the WCF environment cannot insert a deserialized value into the host code, because, based on the data contract, the internal setter part of the property is not available. use the InternalVisibleTo attribute to tell the WCF serialization infrastructure access to the client-side customizer of your data contract object.

+1
source

You need to implement a setter ...

 protected internal set { userRolesTable = value; } 
0
source

Basically, this is a serialization issue. I had this problem in my code in the past, but some time has passed, so bear with me.

First we need to find out if the object relations are null before calling WCF, so send debug information before and after.

If the object is returned as null before the call, you have several options:

  • You can explicitly use .Include ("AnotherObject") in your DbContext to get the object. I used this when my Read method accepted an array of strings into which I used all the necessary objects. This is more convenient than automatically taking all objects, because during serialization, if you take everything, you can pretty easily complete your entire database, which will be serialized, which, among other things, will add performance and security concerns.

  • Another option is to use a dynamic proxy by adding the virtual keyword in front of your list. However, in DataContractSerializer there is a problem with serializing dynamic proxies, so you will need to implement an attribute that uses ProxyDataContractResolver instead of DataContractResolver. This attribute should apply to all OperationContracts that can transmit dynamic proxies. This will automatically accept ALL object references, which is probably a bad coding practice, so I recommend this method.

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

Edit: I also think that your setters in the Data Contracts may not be public, because I do this and it works fine :). But first, I'll try to make your setter open, and then solve the problem, and then return to the secure network device so that you deal with as few variables as possible at a time.

0
source

All Articles