Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is WCF serializing a Enum as a string?

Tags:

vb.net

wcf

Code on the server

<DataContract(Namespace:="http://schema.aam.us.com/2010/6", Name:="TradeStatus")>
Public Enum TradeStatus

    NewOrder = 100
    SendToProvider = 101
    ProviderSubmitted = 102
    ProviderAccepted = 103
    ExecutionPending = 104
    Executed = 105
    TicketsCreated = 106 'TERMINAL STATE

End Enum

<DataContract(Namespace:="http://schema.aam.us.com/2010/6", Name:="StatusUpdate")> _
Public Class StatusUpdate

    Public Sub New(ByVal tradeStatus As TradeStatus, ByVal additionalInformation As String)
        Me.TradeStatus = tradeStatus
        Me.AdditionalInforamtion = additionalInformation
    End Sub

    <DataMember(IsRequired:=True)> _
    Public Property AdditionalInforamtion() As String

    <DataMember(IsRequired:=True)> _
    Public Property TradeStatus() As TradeStatus
End Class

Generated code

<System.Diagnostics.DebuggerStepThroughAttribute(),  _
 System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"),  _
 System.Runtime.Serialization.DataContractAttribute(Name:="StatusUpdate", [Namespace]:="http://schema.aam.us.com/2010/6"),  _
 System.SerializableAttribute()>  _
Partial Public Class StatusUpdate
    Inherits Object
    Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged

    <System.NonSerializedAttribute()>  _
    Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject

    Private AdditionalInforamtionField As String

    Private TradeStatusField As String

    <Global.System.ComponentModel.BrowsableAttribute(false)>  _
    Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData
        Get
            Return Me.extensionDataField
        End Get
        Set
            Me.extensionDataField = value
        End Set
    End Property

    <System.Runtime.Serialization.DataMemberAttribute(IsRequired:=true)>  _
    Public Property AdditionalInforamtion() As String
        Get
            Return Me.AdditionalInforamtionField
        End Get
        Set
            If (Object.ReferenceEquals(Me.AdditionalInforamtionField, value) <> true) Then
                Me.AdditionalInforamtionField = value
                Me.RaisePropertyChanged("AdditionalInforamtion")
            End If
        End Set
    End Property

    <System.Runtime.Serialization.DataMemberAttribute(IsRequired:=true, EmitDefaultValue:=false)>  _
    Public Property TradeStatus() As String
        Get
            Return Me.TradeStatusField
        End Get
        Set
            If (Object.ReferenceEquals(Me.TradeStatusField, value) <> true) Then
                Me.TradeStatusField = value
                Me.RaisePropertyChanged("TradeStatus")
            End If
        End Set
    End Property

    Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Protected Sub RaisePropertyChanged(ByVal propertyName As String)
        Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent
        If (Not (propertyChanged) Is Nothing) Then
            propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
        End If
    End Sub
End Class
like image 740
Jonathan Allen Avatar asked Jul 06 '10 20:07

Jonathan Allen


1 Answers

Enums are serialized by default. Like primites and Collection classes you do not need to mark them with [DataContract]. However, that does not mean that WCF does not let you customize the serialization behavior, so in the spirit of interoperability you can change how the enum will be serialized. As part of that customizability if you mark it with DataContract but do not mark EnumMembers you are changing the default serialization scheme. See more on Enum serialization here Enum Serialization

EDIT: Got to thinking a bit more about this and now I started wondering about the underlying cause... turns out it is the WSDL's fault.

By default if you don't put [DataContract] then WCF by default serializes the enum as if it had the [DataContract] and [EnumMembers] attribute. So if you take the following example

[DataContract]
public enum FileType {
    [EnumMember]
    Text,
    [EnumMember]
    Pdf,
    [EnumMember]
    Word
}

it will generate the following WSDL

<xs:simpleType name="FileType">
  <xs:restriction base="xs:string">
    <xs:enumeration value="Text" /> 
    <xs:enumeration value="Pdf" /> 
    <xs:enumeration value="Word" /> 
  </xs:restriction>
</xs:simpleType>
<xs:element name="FileType" nillable="true" type="tns:FileType" />

So now if you take out the [EnumMember] attributes like so

[DataContract]
public enum FileType {
    Text,
    Pdf,
    Word
}

your WSDL will look like this:

<xs:simpleType name="FileType">
  <xs:restriction base="xs:string" /> 
</xs:simpleType>
<xs:element name="FileType" nillable="true" type="tns:FileType" />

So the second one looks just like the first one except without the enumeration elements. Now what is the difference between the second one and just a WSDL describing a simple string? None. That is why the WCF Proxy gen gives you a string instead of the Enum.

like image 54
John K Avatar answered Sep 18 '22 16:09

John K