views:

716

answers:

2

I'm not certain where the error is resulting (from silverlight, from wcf, something else...) but, I have a WCF service being called from Silverlight. The method returns a class, with a property that does not have a setter. This throws an error. If I add a setter to the property then it does not give an error.

The error is the usual impenetrable and unhelpful Silverlight error message, but...

[Serializable]  
[DataContract]  
public SomeClass {  
    DataMember]  
    public string PropertyA { get; set; }  
    public string PropertyB { get { return "Hi There"; } }  
}

Throws an error...

But change it to:

[Serializable]  
[DataContract]  
public SomeClass {  
     [DataMember]  
     public string PropertyA { get; set; }  
     public string PropertyB { get { return "Hi There"; } set {} }  
}

No error.

Includes the usual ISomeService.svc & SomeService.svc class, references updated in Silverlight calling the client async, etc., etc.

What is the correct way to configure the property (some attribute other than "DataMember" to allow a get-only, or a private-set property) to pass it over the wire?

A: 

In your example PropertyB is not marked with a DataMember attribute meaning that it won't be exposed in the WSDL and ignored by the serializer. But if you mark PropertyB with a DataMember then you must have a setter (private, proptected or public) in order to serialize it correctly otherwise you may get an exception. There are two ways I can think of having read-only properties serialized over the wire:

[DataContract]
public class SomeClass
{ 
    public SomeClass()
    {
        _propertyB = "Hi there";
    }

    [DataMember(Name="PropertyB")]
    private readonly string _propertyB;

    public string PropertyB
    {
        get { return _propertyB; }
    }
}

Or this:

[DataContract]
public class SomeClass
{ 
    public SomeClass()
    {
        PorpertyB = "Hi there";
    }

    [DataMember]
    public string PropertyB
    {
        get;
        private set;
    }
}

Please note that if you use svcutil.exe, the generated proxy class will have both public getter and setter for the property which might not be what you are looking for. In this case you can use the service contract and data contract assemblies on the client side.

Darin Dimitrov
+1  A: 

Thanks. The private set seem to be sufficient. I don't like having the set method there when it is not needed but I can throw an error if it is accessed.

[DataMember]  
public PropertyB {  
    get {  
         return "Hi there";  
    }  
    private set {  
         throw new Exception("Empty setter for use by WCF Service.");
    }  
}

Or whatever.