How to cast Azure DocumentDB Document class to my POCO class? How to cast Azure DocumentDB Document class to my POCO class? azure azure

How to cast Azure DocumentDB Document class to my POCO class?


If you need to map your Document to your POCO in the function then the easiest way to do that is what you suggested.

Call the document.Resource.ToString() method and use DeserializeObject from JSON.NET or the json library you prefer. JSON.NET is recommended however as Microsoft's CosmosDB libraries use it as well.

Your mapping call will look like this:

var yourPoco = JsonConvert.DeserializeObject<YourPocoType>(document.Resource.ToString())


While solution offered by Nick Chapsas works, I would like to offer a few better options.

Preferred solution - improve your model

First, if you are interested in the extra meta fields then you can always include the chosen properties into your data access model and they will be filled in. for example:

public class Model{    public String id { get; set; }    public String _etag { get; set; }    //etc.}

Then you can use the existing API for deserializing thats explicit and familiar to all. For example:

var explicitResult = await client.ReadDocumentAsync<Model>(documentUri);Model explicitModel = explicitResult.Document;

If you want the next layer model (ex: domain model) to NOT have those storage-specific meta fields then you need to transform to another model, but that is no longer a cosmosDB-level issue and there are plenty of generic mappers to convert between POCOs.

This is the IMHO cleanest and recommended way to handing data access in cosmosDB if you work on strongly typed document models.

Alternative: dynamic

Another trick is to use dynamic as the intermediate casting step. This is short and elegant in a way, but personally using dynamic always feels a bit dirty:

var documentResult = await client.ReadDocumentAsync(documentUri);Model dynamicModel = (dynamic)documentResult.Resource;

Alternative: read JObject

Another alternative is to read the document as NewtonSoft's JObject. This would also include all the meta fields and you could cast it further yourself without all the extra hopping between string representations. Example:

var jObjectResult = await client.ReadDocumentAsync<JObject>(documentUri);Model JObjectResult = jObjectResult.Document.ToObject<Model>();

Alternative: Document + JObject at the same time

Should you really-really want to avoid the document level meta fields in model AND still access them then you could use a little reflection trick to get the JObject from the Document instance:

var documentResult = await client.ReadDocumentAsync(documentUri);Document documentModel = documentResult.Resource;var propertyBagMember = documentResult.Resource.GetType()    .GetField("propertyBag", BindingFlags.NonPublic| BindingFlags.Instance);Model reflectionModel = ((JObject)propertyBagMember.GetValue(documentResult.Resource))    .ToObject<Model>();

Beware that the reflection trick is relying on the internal implementation details and it is not subject to backwards compatibility guarantees by library authors.


You can simply do a .ToString() in the Microsoft.Azure.Documents.Document class.

This class inherits from the Microsoft.Azure.Documents.JsonSerializable class that overrides the .ToString() method.

Here below is an example of deserializing the Document class to my Car.cs POCO using the new high-performant System.Text.Json Namespace:

Car car = JsonSerializer.Deserialize<Car>(document.ToString());