Fabiano
Fabiano

Reputation: 5194

WCF Service default values

I have following data contract class for my WCF Service:

[DataContract(Name = "MyClassDTO")]
public class MyClass
{
    private string name = "Default Name";

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

When I use Visual Studio's Add Service Reference function to generate a WCF Service Reference the generated DataContract looks something like this:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name = "MyClassDTO", Namespace = "xxx")]
[System.SerializableAttribute()]
public partial class MyClassDTO : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged
{

    [System.Runtime.Serialization.OptionalFieldAttribute()]
    private string NameField;

    [System.Runtime.Serialization.DataMemberAttribute()]
    public string Name
    {
        get
        {
            return this.NameField;
        }
        set
        {
            if ((object.ReferenceEquals(this.NameField, value) != true))
            {
                this.NameField = value;
                this.RaisePropertyChanged("Name");
            }
        }
    }
}

That means, the default value "Default Name" gets lost and following behavior occurs:

MyClassDTO mcdto = new MyClassDTO();
serviceClient.DoSomething(mcdto);


[OperationContract]
void DoSomething(MyClass mc){
   mc.Name //<--   == null    but I want it to be "Default Name"
}

Is there a way configure the data contract that way, that the defined default value "Default Name" doesn't get lost?

additional information: I use a service reference without reuse of types in referenced assemblys, e.g. on the client side the class MyClassDTO is generated an is not aware of the server side class MyClass

Upvotes: 10

Views: 10027

Answers (4)

Fabiano
Fabiano

Reputation: 5194

The only possible (but ugly and therefore not really satisfying) solution I found this far is using the OnDeserializing attribute to set the default values at the start of the deserialization an use the setter of a field to determine if the communicated value should realy be set.

   [DataContract(Name = "MyClassDTO")]
    public class MyClass
    {
        private string name;

        public MyClass()
        {
            Init();
        }

        [DataMember]
        public string Name
        {
            get{ return name; }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    name = value;
                }
            }
        }

        private void Init()
        {
            name = "Default Name";
        }

        [System.Runtime.Serialization.OnDeserializing]
        private void OnDeserializing(StreamingContext ctx)
        {
            Init();
        }
  }

Upvotes: 5

Kwal
Kwal

Reputation: 1531

During deserialization, the 'set' logic of your property will be executed, so you could check for null there and set to whatever your desired default is at that point.

Upvotes: 1

John Saunders
John Saunders

Reputation: 161791

I don't believe that XML Schema allows the description of a default value of an element. This means that, as far as a client of your service is concerned, there is no default value.

Besides which, you've done nothing to tell WCF that you mean to have a default value, so even if there were a way to communicate your intent to a client, the fact is that you're not communicating your intent.

Upvotes: 2

Marc Gravell
Marc Gravell

Reputation: 1063338

Hmmm.. I thought that there were some things with [DefaultValue(...)] that would work, but apparently not; I'm a bit confused why you get null, though - since you haven't told it about any default I would expect "Default Name" to get into the output. If you have some default code (or a ShouldSerialize* / *Specified) then you could try:

[DataMember(EmitDefaultValue=true)]
public string Name {
    get { return name; }
    set { name = value; }
}

But again - I'm not entirely sure why you are seeing a null in the first place.

I've just tested this with something based on the WCF template in VS2008, and it works fine:

using (var client = new Service1Client()) {
    var result = client.GetDataUsingDataContract();
    Console.Write(result.Name); // "Default Name"
}

Upvotes: 2

Related Questions