WCF: DataMember attribute on property vs. member

.NetWcfSerialization

.Net Problem Overview


In wcf, what is the difference between applying the DataMember attribute on a property

private int m_SomeValue;

[DataMember]  
public int SomeValue {
  get {...}
  set {...}
}

instead of a member variable

[DataMember]  
private int m_SomeValue;

public int SomeValue {
  get {...}
  set {...}
}

?

.Net Solutions


Solution 1 - .Net

In general, you should favor applying the DataMember attribute on the property, rather than on the private field. The only reason to apply the attribute to the field instead is if the property were read-only (i.e. it has no setter).

Solution 2 - .Net

As long as you use the Name marker, the contract is identical regardless of whether the field or property is used.

[DataMember(Name="SomeValue")]
private int m_SomeValue;

However, there may be some permissions issues accessing private members, in particular on silverlight and CF - in which case I would recommend using the public property as the data-member. Actually, I would tend to always use a property unless I had a very good reason...

Solution 3 - .Net

There are good reasons you may want to mark fields rather than properties as DataMember .

Please check this for more details : http://blog.walteralmeida.com/2010/05/wcf-and-datacontract-serialization-internals-and-tips-.html

By the way: ContractSerializers will serialize any private field that has the DataMemberAttribute on it only if running in full trust environment. Does not work in partial trust (check the blog listed above for a solution)

Solution 4 - .Net

This decission depends on the usage of you WCF service:

  1. Internal service consumed by you own .NET systems, that share the same Domain Model.
  2. External service consumed by different platforms, that do not share same Domain Model.

Case 1.

Serialization - is the process of persisting the state of the object. The state of the object in C# is represented by it's data fields.

Properties in C# are essentially - methods, which manipulate the state of the object. Using them can result in different object state ofter deserialization, because the order in which properties are set can have impact on it's final data state. Other factors can result in incorrect state deserialization too, if for example method (property set) relies on some context that is changing, like current DateTime.

You may say what about encapsulation? I don't want my object to be in invalid state, and I must do validation checks, object graph integrity checks, etc. Yes, you should, so we put the DataMember attribs on props? No.

The problem here is that lot's of people mix two different things, DTO (Data Transfer Object, WCF Contract) with Domain Entity. What you need is ensure that the data you recieve is exectly the same data that was send, and then ensure that you can construct valid Domain Entity from this data. The best way to achieve this is use separate classes for DTO's, and construct Domain Entity from them.

But most programmers are lazy, and they like to simple decorate Domain Entity with DataMemeber attributes. In this case the decision Field or Prop depends on where your validation logic is, if your validation logic is buried in Set methods, you will have to use Props, if it's extenral you should use Fields, and validate you Domain Entity after desirialization.

P.S. I think the same rules apply to any serialization process, like data base persistnce.

Also, I would like to mention that Silverlight can't serialize\deserialize private fields, because you can't access them from outside using reflection, and you will have to make them private and use InternalsVisibleToAttribute.

Case 2.

This is hard one. The main focus here is interoperability. In 99.9% you will have separate DTO classes in this case and most likely lot's of different versions of them to support old clients. It doesn't matter where you put DataMembers attribs in this, because you use DTO's. I will not bother with explaining this scenario, because developers who work on such large scale system are usually quite experienced, and they don't bother reading SO.

Solution 5 - .Net

In theory, and as long as you keep m_SomeValue always equal to SomeValue (like a simple getter/setter), nothing. Other than the name of the variable exposed by the WCF. (Obviously, if you tag the m_ variable, then your proxy class will also have the same m_ name. The proxy class will generate a public property whether you use a public/protected/internal/private field or property.

However, if you have any special logic in your accessors that may modify the value returned (ToUpper()ing a string, for example), then you would return a different value.

Solution 6 - .Net

Personally I would just use the property and completely removed the member variable all together. i.e.

[DataMember]
public int SomeValue
{ get; set; }

The property will inexplicably create a member variable behind the scenes.

Solution 7 - .Net

If add [DataMember] on private int m_SomeValue, this member can not be serialization,so must be add it on public int SomeValue.

[DataMember]  
private int m_SomeValue;

public int SomeValue {
  get {...}
  set {...}
}

the code of above can not be get value in the client if you use it through WCF.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJulien PoulinView Question on Stackoverflow
Solution 1 - .NetdthrasherView Answer on Stackoverflow
Solution 2 - .NetMarc GravellView Answer on Stackoverflow
Solution 3 - .NetWalter AlmeidaView Answer on Stackoverflow
Solution 4 - .NetAlex BurtsevView Answer on Stackoverflow
Solution 5 - .NetJarrett MeyerView Answer on Stackoverflow
Solution 6 - .Netbj.View Answer on Stackoverflow
Solution 7 - .NetshawdrenView Answer on Stackoverflow