Serialization Settings

Since version 1.15.0, Azure’s CosmosDB SDK supports JsonSerializerSettings as a paramater. This gives us the ability to define custom contact serializer and how to handle null values.

This is easy as this:

var serializerSettings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    ContractResolver = new CamelCasePropertyNamesContractResolver()	
};

var client = new DocumentClient(endpointUrl, authorizationKey, serializerSettings);

The base class issue

When you create a document into CosmosDB you will realize that in addition to your own properties, some system properties prefixed with an underscore (_) are added and returned when quering the document:

Property Purpose
_rid System generated, unique, and hierarchical identifier of the resource
_etag etag of the resource required for optimistic concurrency control
_ts Last updated timestamp of the resource
_self Unique addressable URI of the resource

Add the required id propery that is either set by the user or auto-generated by the system if ommited.

In a way to reduce your typing, you could be tempted to inherits your documents from the Microsoft.Azure.Documents.Document class that it the class returned by most of the calls to the SDK. Unfortunatly, it doesn’t work in many fashions:

  • Properties are not serialized if they are not marked with the [JsonProperty]attribute.
  • JsonSerializerSettings are not respected!

The persistance of this class

public class InheritFromDocument : Microsoft.Azure.Documents.Document
{
    [JsonProperty] 
    public string Firstname { get; set; } = "Inherit";
    [JsonProperty]
    public string Lastname { get; set; } = "Document";
    [JsonProperty]
    public string NotDefinied { get; set; } = null;
}

will result into a JSON where our user-defined properties are not correctly camel cased despite the definied Contract Resolver and the null values are serialized :

{
  "Firstname": "Inherit",
  "Lastname": "Document",
  "NotDefinied": null,
  "id": "dcf88cbf-d3ee-4558-b698-a94006d0d49c",
  "_rid": "Ho1MAP0xtwqKAAAAAAAAAA==",
  "_self": "dbs/Ho1MAA==/colls/Ho1MAP0xtwo=/docs/Ho1MAP0xtwqKAAAAAAAAAA==/",
  "_etag": "\"00000000-0000-0000-c501-e64f859b01d3\"",
  "_attachments": "attachments/",
  "_ts": 1522069007
}

In another hand, if you inherit your documents from Microsoft.Azure.Documents.Resource you will get a correct serialization.

public class InheritFromResource : Microsoft.Azure.Documents.Resource
{
    public string Firstname { get; set; } = "Inherit";
    public string Lastname { get; set; } = "Resource";
    public string NotDefinied { get; set; } = null;
}
{
  "firstname": "Inherit",
  "lastname": "Resource",
  "id": "5e1211e8-4589-436a-bfa0-a17dea4accf8",
  "_rid": "Ho1MAP0xtwqLAAAAAAAAAA==",
  "_self": "dbs/Ho1MAA==/colls/Ho1MAP0xtwo=/docs/Ho1MAP0xtwqLAAAAAAAAAA==/",
  "_etag": "\"00000000-0000-0000-c501-e6542d2801d3\"",
  "_attachments": "attachments/",
  "_ts": 1522069007
}

You can also create documents from your own POCO but you will have to handle the system properties by hand if you need to retrieve them.

public class POCO 
{
    public string Id { get; set; }
    public string Firstname { get; set; } = "Po";
    public string Lastname { get; set; } = "Co";
    public string NotDefinied { get; set; } = null;
}

Summary

Don’t use Microsoft.Azure.Documents.Document as your base class for storing document. It will not respect your settings!

Microsoft.Azure.Documents.Resource is a far better alternative. POCO are as always a good fit. It doesn’t tie you to a specific implementation or SDK and you can easily create a base class that will handle the system properties.