53

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

?

Enrico Campidoglio
  • 56,676
  • 12
  • 126
  • 154
Julien Poulin
  • 12,737
  • 10
  • 51
  • 76

7 Answers7

41

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).

dthrasher
  • 40,656
  • 34
  • 113
  • 139
  • 2
    Why do we need to do that though? – Krishna Apr 12 '10 at 07:42
  • 2
    All serialization in WCF is two-way by default. This means that the framework needs to be able to read and write all of your data elements. So if you are modifying an existing type with read-only properties to be serializable, you might have to add the attributes to a field. This is a rare case, though. – dthrasher Apr 12 '10 at 13:21
  • 5
    It's also useful to put the DataMemberAttribute on a field if your property's getter/setter has any code that might alter its value. – rossisdead May 21 '10 at 03:28
  • 1
    @rossisdead Except where this may be the intended behavior. – Tri Q Tran Nov 09 '12 at 04:40
24

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

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I totaly disagree with you Marc, see my asnwer, I would like to hear your reply on it http://stackoverflow.com/a/8442768/235715 – Alex Burtsev Dec 09 '11 at 08:24
6

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)

Walter Almeida
  • 227
  • 3
  • 2
4

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.

Alex Burtsev
  • 12,418
  • 8
  • 60
  • 87
  • When it comes to platform-bound, type-bound serialization - then yes! the fields do indeed represent the state. I'm thinking `BinaryFormatter` etc here. However, in terms of an **interoperable** piece of data, where the receiving type is **not** identical (it could be mex/wsdl-generated, or could be a completely different platform), we should have **no knowledge** of (or dependency upon) the fields. Yes validation remains important, and there are mechanisms for that (and other things, such as callbacks). – Marc Gravell Dec 09 '11 at 08:30
  • Further; the job of serialization is *not* simply "persisting the state of the object" - it is doing that *in the way that matches the protocol*. For BinaryFormatter, that means (by defualt) "the fields", but for WCF... not so much. The **data** is not `m_someValue` - the *data* is `SomeValue`. `m_someValue` is an implementation detail. There are ways to handle the mapping (such as : using `Name` on the field to make `m_someValue` appear as `SomeValue`) – Marc Gravell Dec 09 '11 at 08:34
  • @MarcGravell I agree with you on the part of interoperability, I'm thinking on this subject as a simple procceess of persisting and restoring state, but it's more then that. My answer basically applies only to situation when you have C# on both ends, and you reuse same classes. If we take for example situation when we have C# code as receiver and PHP code as sender, then situation is a little diferent, I need some time to consider this, than I think I will update my answer. – Alex Burtsev Dec 09 '11 at 08:45
  • 2
    The question, though, is not "persisting and restoring state" - it is WCF. WCF is *by design and intent* a platform neutral, implementation agnostic, communication transport. Even if it is C# to C#, it is **not** required that the same assembly is at both ends; merely that they use the same *contract*. And a contract has nothing whatsoever to do with fields. – Marc Gravell Dec 09 '11 at 13:21
  • @MarcGravell And the contract has nothing to do with Properties either. It does care only about XML elements, and your DTO represents this Contract in programming enviroment, and should have no logic. So it's fields. – Alex Burtsev Dec 09 '11 at 13:36
  • it is neither properties **nor** fields ;p or both! It is just about *however you bind your type to the contract*, hence my answer stating that the attribute could be applied to either **with the same result**. Re not having logic; it is more abstract than that, even; it is simply not specifically fields. Your choice of mapping the logic to fields is simply a mapping detail; mapping to properties is also entirely valid in virtually all scenarios (more so than fields, IMO - having done quite a bit of serialization work). – Marc Gravell Dec 09 '11 at 13:46
  • @MarcGravell I guess we will stay each with it's own opinion :-) – Alex Burtsev Dec 09 '11 at 13:56
3

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.

Jarrett Meyer
  • 19,333
  • 6
  • 58
  • 52
2

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.

sth
  • 222,467
  • 53
  • 283
  • 367
bj.
  • 21
  • 1
  • 7
    "inexplicably"? That's what it's meant to do. Perhaps you meant "implicitly"? – John Saunders Oct 28 '09 at 06:41
  • The C# compiler generates a private "backing" field with a mangled name (to prevent colliding with the name of any other field you may have defined) for the auto-property. – Kit Jun 17 '10 at 16:24
1

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.

Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
shawdren
  • 11
  • 1
  • 3
    DataContractSerializers will serialize any private field that has the DataMemberAttribute on it. – rossisdead May 21 '10 at 03:27
  • I agree with rossisdead, any private field has DataMemberattribute gets serialised, and is exposed by service to the client. – Niraj Dec 13 '12 at 06:55