Back to more Windows Communication Foundation (WCF, previously - Indigo), or previously known as Indigo, postings...
I dont think a lot of people know about one of the aspects of WCF, which pertains to how WCF serializes incoming messages before it sends it to the dispatcher and onto your .NET typed code.
In .NET 1.*, ASMX disregards the ordering of the data elements in the received messages. This means that for a XML Schema such as this:
[s:complexType name="CreditCard"]
[s:sequence]
[s:element name="AccountName" type="s:string" /]
[s:element name="CreditCardType" type="s:string" /]
[s:element name="CreditCardNo" type="s:string" /]
[s:element name="CreditCardExpiryDate" type="s:string" /]
[/s:sequence]
[/s:complexType]
If you send a (W3C) SOAP Message such as this (Take note that the ordering of [AccountName] is not in-line with the above schema):
[soap:Envelope]
[soap:Header /]
[soap:Body]
[SubmitCreditCard]
[crdcard]
[CreditCardType]AMEX[/CreditCardType]
[CreditCardNo]1234567890[/CreditCardNo]
[CreditCardExpiryDate]08082088[/CreditCardExpiryDate]
[AccountName]William Tay[/AccountName]
[/crdcard]
[/SubmitCreditCard]
[/soap:Body]
[/soap:Envelope]
ASMX will allow the message to go through.
In WCF, there is strict enforcing of the ordering of the data elements. Lets take a quick look:
WCF Code:
[DataContract()] _
Public Class CreditCard
[DataMember(Name:="CreditCardExpiryDate")] Private _CreditCardExpiryDate As String
[DataMember(Name:="CreditCardType")] Private _CreditCardType As String
[DataMember(Name:="CreditCardNo")] Private _CreditCardNo As String
[DataMember(Name:="AccountName")] Private _AccountName As String
Public Property CreditCardType() As String
Get
Return _CreditCardType
End Get
Set(ByVal value As String)
_CreditCardType = value
End Set
End Property
Public Property CreditCardNo() As String
Get
Return _CreditCardNo
End Get
Set(ByVal value As String)
_CreditCardNo = value
End Set
End Property
Public Property CreditCardExpiryDate() As String
Get
Return _CreditCardExpiryDate
End Get
Set(ByVal value As String)
_CreditCardExpiryDate = value
End Set
End Property
Public Property AccountName() As String
Get
Return _AccountName
End Get
Set(ByVal value As String)
_AccountName = value
End Set
End Property
End Class
This will generate the schema:
[xs:complexType name="CreditCard"]
[xs:sequence]
[xs:element name="AccountName" nillable="true" type="ser:string" /]
[xs:element name="CreditCardExpiryDate" nillable="true" type="ser:string" /]
[xs:element name="CreditCardNo" nillable="true" type="ser:string" /]
[xs:element name="CreditCardType" nillable="true" type="ser:string" /]
[!-- I omitted some WCF-specific elements here for simplicity.--]
[!--I will blog more about this on a later date. See Below **--]
[/xs:complexType]
There is a reason I put the Public Property AccountName last in my .NET 2.0/Indigo code above. I wanted to show that how you place the property/field in code has no effect on the schema. If you keep a strong observant eye on the resultant schema, you will notice that it is Alphabetical-Ordering dependent and if I send the below message to it:
[s:Envelope]
[s:Header /]
[s:Body]
[SubmitCreditCard xmlns="http://demos.softwaremaker.net/SchemaDataOrdering"]
[crdcard]
[CreditCardExpiryDate]08082088[/CreditCardExpiryDate]
[CreditCardNo]1234567890[/CreditCardNo]
[CreditCardType]AMEX[/CreditCardType]
[AccountName]William Tay[/AccountName]
[/crdcard]
[/SubmitCreditCard]
[/s:Body]
[/s:Envelope]
It will result in a HTTP Error Code: 500 (Internal Server Error). What this means is that you have to keep the ordering of the dispatched message to the published schema or else WCF will reject it.
The consensus from the field (I felt) is that while most of the projects doesnt even feel the lack of schema-ordering enforcements in .NET 1.*, there may be certain advanced validation scenarios that may need order checking at the schema level. While I welcomed this extra checking, I hope it doesnt come with a performance penalty.
The good news is that the Service.Runtime.Serialization.XMLFormatter, which is used in WCF, is a lot better performer than its predecessor: the XMLSerializer. It does, however, give the developer less control of the XML Schema though. **WCF will add in its own special elements into the schema**. This will aid in better message versioning and control that comes with the evolutionary nature of distributed loosely-coupled messaging systems such as WCF. I will explain more in a later blog post.
From what I understand, the WCF team is considering of adding an Order property to the DataMemberAttribute to allow for added customization of this order. Again, I feel that this is a good move as Alphabetical-Ordering dependency will mean that developers may have to consider their naming conventions in code should they require a validation check at the schema level.
What I would like is an attribute for me to turn-off schema data elements ordering validation and checking should I choose to. In this case, the developers on the field will be comfortable of the options they have at hand if validation / performance tradeoffs becomes an issue.
P/S: I used my own Manual SOAP Post tool to create some of the scenarios here. You may want to download it here.