WCF: DataMember attribute on property vs. member
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 {...}
}
?
Solution 1:
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:
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:
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:
This decission depends on the usage of you WCF service:
- Internal service consumed by you own .NET systems, that share the same Domain Model.
- 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:
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.