DataContract weird characters and Mono

My solution will run on dotNET and Mono in a variety of mixes. Connecting the pieces of the Service Oriented Architecture design using WCF. Testing some setups showed me
another difference between dotNET and Mono. The returntype of an operation is Generic Dictionary with a string and a custom type. Would we have used standard System types this would not have been a problem.

I’ll demonstrate this by using a small service that returns authors and books. See code below. The client will receive the information and display the number of items in the result (and some other details). Implementation in the sample project at the end of my post.

[ServiceContract(Namespace = "http://my.solution/2012/04")]
public interface IBookService
{
    [OperationContract]
    Dictionary<string, BookData> GetOneBookPerAuthor();
}

[DataContract(Namespace = "http://my.solution/2012/04")]
public class BookData
{
    [DataMember]
    public string Title { get; set; }

    [DataMember]
    public int Id { get; set; }
}

Depending on the framework (dotNET or Mono) the results differ:

Service Client Result
.NET .NET 2 items
.NET Mono 2 items
Mono Mono 2 items
Mono .NET 0 items

The problem is in the serialization of datacontracts. Where Mono uses the same name as the class for the intermediate type: KeyValueOfstringBookData the dotNET framework does it a little different: KeyValueOfstringBookData6LZ3tCpf (notice the weird stuff at the end). This post on mono-for-android forum of Ximian shed some light.

My solution is to alter the message before it is send to the client when the service is hosted in Mono. For this I’ll use the IDispatchMessageInspector from WCF. In the BeforeSendReply method the KeyValueOfStringBookData tag is replaced with KeyValueOfstringBookData6LZ3tCpf.

public void BeforeSendReply(ref Message message, object instance)
{
    // get the message body
    var bodyReader = message.GetReaderAtBodyContents();
    bodyReader.Read();
    // replace to get the weird characters needed for dotNET clients
    var msg = bodyReader.ReadOuterXml().Replace("KeyValueOfstringBookData>", "KeyValueOfstringBookData6LZ3tCpf>");
    // construct the new message
    var stringreader = new StringReader(msg);
    var xmlreader = XmlReader.Create(stringreader);
    var xmldictionaryreader = XmlDictionaryReader.CreateDictionaryReader(xmlreader);
    var replacedMessage = Message.CreateMessage(message.Version, null, xmldictionaryreader);
    replacedMessage.Headers.CopyHeadersFrom(message.Headers);
    replacedMessage.Properties.CopyProperties(message.Properties);
    // set the new message as THE message
    message = replacedMessage;
}

To find the weird characters for your implementation, host the service in dotNET and request the WSDL. You’ll propably need to dig a little deeper by requesting the ?xsd=xsd0-9 stuff but the information is there


sample project

About erictummers

Working in a DevOps team is the best thing that happened to me. I like challenges and sharing the solutions with others. On my blog I’ll mostly post about my work, but expect an occasional home project, productivity tip and tooling review.
This entry was posted in Development and tagged , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.