.NET Service Reference and specified properties for optional elements
When you generate a Service Reference in Visual Studio for a web-service, you can often find a bunch of xxxSpecified boolean properties. These are from optional XML elements as per the service contract / WSDL.
For example, consider this XSD definition for a structure:
<xs:element name="MyObject"></xs:element><xs:element name="MyObject"> <xs:complextype> <xs:sequence> <xs:element maxoccurs="1" minoccurs="0" name="Date" type="xs:dateTime"> </xs:element></xs:sequence> </xs:complextype> </xs:element>
The service/WCF proxy will generate a class that looks a bit like this:
public partial class MyObject : object, INotifyPropertyChanged { private DateTime dateField; private bool dateFieldSpecified; [XmlElement] public DateTime Date { get { return this.dateField; } set { this.dateField = value; this.RaisePropertyChanged("Date"); } } public event PropertyChangedEventHandler PropertyChanged; }
I've simplified the generated code a bit. The important thing here is the "Specified" property that is generated. This happens when a minOccurs="0" is in the service XSD. It's the only clear way to tell whether an optional element was sent or not. Personally, I'd like to see an option in the Service Reference Configuration to allow this to be manifested as Nullable<>, but there isn't.
This proves a bit of a coding problem when setting these values for an outgoing request. Simply setting myObjectInstance.Date = DateTime.Now; wouldn't work - whilst the property is set, the Specified co-property is still left as the default "false". You can go and specify each of these individually when you set the data value.
This in turn though is even more problematic when you're doing something like model-binding with MVC. Assume your object is the parameter in a controller method and the values are being populated by the results of a HTML form post - it would be ludicrous (and dangerous) to have the Specified properties being set in your UI.
So what's the solution? You'll note, that when a property is set, it calls the RaisePropertyChanged method (not included in the above generated code, but it will be there actually), which in turn fires an event. You can subscribe to this event and set your Specified property automatically through Reflection.
Luckily Service Reference classes are defined as Partial, which means you can expand out these classes without tinkering with generated code - this is of critical importance as every time you refresh your reference, the main classes will be wiped out along with any changes you've made.
So I've created a second file elsewhere with my custom code:
public partial class MyObject { public MyObject() : base() { this.PropertyChanged += MyObject_PropertyChanged; } private void MyObject_PropertyChanged(object sender, PropertyChangedEventArgs e) { PropertyInfo prop = this.GetType().GetProperty(e.PropertyName + "Specified"); if(prop != null) prop.SetValue(this, true); } }
Whenever the data property is set, it's companion Specified property is automatically set. You have to be careful here with default values in .NET, an int for instance will default to 0, so if that is accidentally assigned then it'll get sent over with your message instead of being left out.