WCF: Show only DataMember properties without set?

I have a server side class that I provide on the client side through [DataContract]. This class has a readonly field that I would like to make available through a property. However, I cannot do this because it does not seem that I am allowed to add the [DataMember] property without receiving or installing and without installing.

So - is there a way to have the [DataMember] property without setter?

[DataContract] class SomeClass { private readonly int _id; public SomeClass() { .. } [DataMember] public int Id { get { return _id; } } [DataMember] public string SomeString { get; set; } } 

Or will the solution use [DataMember] as a field - (for example, shown here )? I tried to do this too, but it seems that he does not care that the field is read only ...?

Edit: Is this the only way to make the readonly property hack it like that? (no - I don't want to do this ...)

 [DataMember] public int Id { get { return _id; } private set { /* NOOP */ } } 
+54
readonly wcf datacontract
Dec 09 '09 at 13:02
source share
5 answers

Your "server" class will not be "really accessible" to the client.

What happens is: based on the data contract, the client will create a new separate class from the XML service schema. It cannot use the server class as such!

It recreates a new class from the definition of an XML schema, but this schema does not contain any specific .NET objects, such as visibility or access modifiers — it's just an XML schema. The client-side class will be created in such a way that it has the same “trace” on the wire - for example, it is basically converted to one XML format.

cannot transfer .NET know-how in a class using a standard SOAP-based service. In the end, all you are looking at is serialized messages — no classes!

Check out the Four Principles of SOA (defined by Microsoft's Don Box):

  • The boundaries are clear.
  • Services are autonomous.
  • Shared Services Schema and Contract, Not Class
  • Policy Based Compatibility

See point 3 - the scheme of general access to services and the contract, the class is not - you just share the interface and the XML scheme for the contract with the data - all .NET classes.

+48
Dec 09 '09 at 13:21
source share

put the DataMember attribute in the field, not the property.

Remember that WCF does not know encapsulation. Encapsulation is the term OOP, not the term SOA.

However, remember that the field will only be for users using your class - anyone who uses the service will have full access to the field on their side.

+10
Dec 09 '09 at 13:11
source share

I had some properties in the class in my service that I wanted to pass to Silverlight. I did not want to create a completely new class.

Not really “recommended”, but it seemed the lesser of two evils to pass the Total property to silverlight (solely for visual data binding).

 public class PricingSummary { public int TotalItemCount { get; set; } // doesnt ideally belong here but used by top bar when out of store area public decimal SubTotal { get; set; } public decimal? Taxes { get; set; } public decimal Discount { get; set; } public decimal? ShippingTotal { get; set; } public decimal Total { get { return + SubTotal + (ShippingTotal ?? 0) + (Taxes ?? 0) - Discount; } set { throw new ApplicationException("Cannot be set"); } } } 
+7
Jul 07 '10 at 5:26
source share

There is a way to achieve this. But it should be warned that this directly violates the following principle given in this answer :

"3. Scheme of access to services and a contract, not a class."

If this violation does not concern you, this is what you do:

  • Move service and data contracts to a separate (portable) class library. (Let us call this assembly SomeService.Contracts .) So you define an immutable class [DataContract] :

     namespace SomeService.Contracts { [DataContract] public sealed class Foo { public Foo(int x) { this.x = x; } public int X { get { return x; } } [DataMember] // NB: applied to the backing field, not to the property! private readonly int x; } } 

    Note that [DataMember] applies to the backup field, and not to the corresponding read-only property.

  • Refer to building contracts from your service application project (I will call mine SomeService.Web ) and from your client projects (mine is called SomeService.Client ). This can lead to the following project dependencies within your solution:

    screenshot highlighting the project dependencies in Solution Explorer

  • Then, when you add the service link to your client project, make sure the "Reuse Types" option is enabled and make sure your contract assembly ( SomeService.Contracts ) is included in this:

    screenshot highlighting the relevant service reference setting

Voila! Visual Studio, instead of generating a new Foo type from the WSDL schema of the service, reuses the immutable Foo type from your contract assembly.

One final warning: you have already deviated from the principles of service indicated in that other answer . But try not to get lost. You might be tempted to start adding (business logic) to your contracted data classes; no. They should stay as close to dumb data transfer objects (DTOs) as you can manage.

+4
Apr 23 '15 at 17:56
source share

Define a service contract (interface). Before executing a contract using a class.

-3
Dec 09 '09 at 13:08
source share



All Articles