Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF: Exposing readonly DataMember properties without set?

I have a server side class which I make available on the client side through a [DataContract]. This class has a readonly field which I'd like to make available through a property. However, I'm unable to do so because it doesn't seem that I'm allowed to add a [DataMember] property without having both get and set.

So - is there a way to have a [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 be use the [DataMember] as the field - (like e.g. shown here)? Tried doing this too, but it doesn't seem to care the field is readonly..?

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

[DataMember]
public int Id
{
    get { return _id; }
    private set { /* NOOP */ }
}
like image 467
stiank81 Avatar asked Dec 09 '09 13:12

stiank81


3 Answers

Your "server-side" class won't be "made available" to the client, really.

What happens is this: based on the data contract, the client will create a new separate class from the XML schema of the service. It cannot use the server-side class per se!

It will re-create a new class from the XML schema definition, but that schema doesn't contain any of the .NET specific things like visibility or access modifiers - it's just a XML schema, after all. The client-side class will be created in such a way that it has the same "footprint" on the wire - e.g. it serializes into the same XML format, basically.

You cannot "transport" .NET specific know-how about the class through a standard SOAP-based service - after all, all you're passing around are serialized messages - no classes!

Check the "Four tenets of SOA" (defined by Don Box of Microsoft):

  1. Boundaries are explicit
  2. Services are autonomous
  3. Services share schema and contract, not class
  4. Compability is based upon policy

See point #3 - services share schema and contract, not class - you only ever share the interface and XML schema for the data contract - that's all - no .NET classes.

like image 172
marc_s Avatar answered Nov 19 '22 06:11

marc_s


put DataMember attribute on a field not the property.

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

That said, remember that the field will be readonly for people using your class - anyone using the service will have full access to the field on their side.

like image 33
Krzysztof Kozmic Avatar answered Nov 19 '22 06:11

Krzysztof Kozmic


I had some properties in a class in my service layer I wanted to pass over to Silverlight. I didn't want to create a whole new class.

Not really 'recommended', but this seemed the lesser of two evils to pass over the Total property to silverlight (solely for visual databinding).

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");
        }
    }
}
like image 8
Simon_Weaver Avatar answered Nov 19 '22 06:11

Simon_Weaver