Architect or Cobbler?
Good code starts with good design

DataContracts and VB - A warning

Thursday, January 04, 2007

We always write our .Net courses as dual language courses, which is kind of hard for me, because I'm not the world's best VB programmer.  So I always do all the exercises as C#, and then convert them to VB at some point.  Yesterday i wasted a whole day because of the way WCF generates proxies for DataContracts.  Let me explain :-)

Just like web services, you can specify namespaces on your code which will be reflected in the WSDL, there is one important differecne however, there are 3 types of contract on which you can specify namespaces:

  • The Service Contract
  • The Message Contract
  • The Data Contract

If you leave the namespaces off then the service contract and the message contract get allocated the standard tempuri.org namespace we all know and love.  If you don't specify the data contract namespace then the framework allocates the namespace http://schemas.datacontract.org/2004/07  + the CLR type.

This is where it starts to go pear shaped, it works fine for C#, but in VB all namespaces belong to the rootnamespace, so instead of your types being serialized accross the wire with a namespace of something like http://schemas.datacontract.org/2004/07/LotteryService/

 they instead are transported accross the wire as

http://schemas.datacontract.org/2004/07/ConsoleApplication2.LotteryService

whereupon they are not deserialized correctly at the other end, and you therefore appear to always get null values sent over the wire.

This is infuriating to say the least, and there doesn't appear to be a great deal you can do to fix it.  Svcutil has a namespace switch which appears to be there to address the issue, so you can map a namespace to a CLR namespace, but it doesn't appear to do very much other than rename the generated proxy namespace.  What it should actually be doing is annotating the DataContractAttribute on the proxy type with the correct namespace, which is what I have to do to fix the problem.

So basically I dive into the the proxy and change all of my DataContracts from 

    <System.CodeDom.Compiler.GeneratedCodeAttribute( _
"System.Runtime.Serialization", "3.0.0.0"), _ System.Runtime.Serialization.DataContractAttribute()> _ Partial Public Class Entry Inherits Object Implements System.Runtime.Serialization.IExtensibleDataObject

to

    <System.CodeDom.Compiler.GeneratedCodeAttribute( _
"System.Runtime.Serialization", "3.0.0.0"), _ System.Runtime.Serialization.DataContractAttribute( _
Namespace:="http://schemas.datacontract.org/2004/07/LotteryService")> _ Partial Public Class Entry

The only problem with that approach is that I lose the annotation whenever the proxy is regenerated.

Of course I could always use namespaces like I'm supposed to :-)


# posted by James @ 7:58 AM   1 comments Comments: would removing the default namespace from the project's properties solve the problem?
# posted by Anonymous darrenb @ 5:19 PM   Post a Comment

<< Main blog page
This page is powered by Blogger. Isn't yours?