Sunday, April 24, 2011

Raven DB and WCF Workflow service contracts

RavenDb is a relatively new (maybe subjective - I’ve heard of it just few month ago) document database built on .NET and for .NET.
It is an extraordinary little (course from user’s point of view) thing which allows to start writing application without extensive database preparation and schema manipulations. It clicks perfectly with MVC, although I am still to discover a similarly elegant technique for Workflow Foundation. Raven Db recognizes property named “Id” (exactly capital “i” and lowercase “d”) as an entity identifier and has some optimization around it, so it is wise to make this field the entity’s identity field. It is even more wise to make it string and assign the value manually while inserting, e.g. using Guid, otherwise you will end up with engine-generated keys like “movies/323” which are deadly for MVC or REST services.
The only problem I’ve noticed so far (and the documentation is scarce on this) – decorating Raven-served documents as a WCF service contracts. I found that some of my workflow variables, which I store in DB, often require to be service contracts.

[DataContract(Namespace = "http://contracts")]
public class Movie : IDocument
{
 [DataMember(IsRequired = true)]
public string Id { get; set; }
 [DataMember(IsRequired = true)]
public string Title { get; set; }
}

It worked perfectly fine in the code until all the sudden I’ve started receiving errors when trying to retrieve the entity from the DB: Newtonsoft.Json.JsonSerializationException: Newtonsoft.Json.JsonSerializationException: Required property 'Id' not found in JSON. With decoration removed, the entity retrieval worked perfectly well. What was strange is that in both cases the document stored looked exactly the same (Raven Db installation includes very helpful Management Studio executed in Silverlight):

The error seemed to only affect “Id” property, which is “invisible”. Obviously something was interfering with JSON deserialization of the object. The Raven API provides great deal of serialization customization but I decided to find laziest easier way to fix the problem.
As it turned out the DataMember attribute was the one to blame. I believe that it is more likely to do with Microsoft’s oversight in DataMember implementation (despite being a member of Serialization namespace it is not being recognized as Serializable) while RavenDb proved to have a perfect reason behind most peculiar decisions. The solution is to add an additional JsonProperty attribute to the troubled field:
[DataContract(Namespace = "http://contracts")]
public class Movie : IDocument
{
[DataMember(IsRequired = true)]
[JsonProperty]
public string Id { get; set; }

[DataMember(IsRequired = true)]
public string Title { get; set; }
}

The attribute class can be found in Newtonsoft.Json namespace. This small addition has fixed the problem (although  entity was shown in the Management Studio entity exactly the same way as before).
also check Feed Burner

2 comments:

Chris Barrow said...

Love the cartoon.

Michael Goldobin said...

I probably should start making my own. Need a writer, though :)


© 2008-2013 Michael Goldobin. All rights reserved