It’s been a while since I looked at CosmosDB (there is a chapter in my book - to the right of your screen - that covers some details of using CosmosDD, but using the MongoDB Api. To get going with Cosmos, you obviously need to create yourself a Cosmos resource in the Portal (or somehow). Once that’s done, you can interact with it using the package:
Microsoft.Azure.Cosmos
You need to create a client, database, and container:
var cosmosClient = new CosmosClient(endpointUri, primaryKey, options);
var database = await cosmosClient.CreateDatabaseIfNotExistsAsync(databaseId);
var container = await database.CreateContainerIfNotExistsAsync(containerId, $"/{partition}");
You can then add to the container like this:
var response = await container.CreateItemAsync<ItemType>(newItem, new PartitionKey(partitionKey));
In this post, I wanted to cover a couple of errors that I got when trying to use it, and some possible solutions. For this post, I was using the Core (SQL) API.
You Need an ID
The first error was:
Microsoft.Azure.Cosmos.CosmosException: ‘Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: cdf12360b-0cbc-4575-9a1c-966f26c2351a; Reason: (Message: {“Errors”:[“The input content is invalid because the required properties - ‘id; ’ - are missing”]}
The reason here is that, when you’re writing to the DB, you need an “ID” field; or, more specifically, an “id” field. This means that either your model should have a field names “id”, or you should reference that name in a Json Property, or you can call it “Id”, and use something like this:
var options = new CosmosClientOptions()
{
SerializerOptions = new CosmosSerializationOptions()
{
PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
}
};
var cosmosClient = new CosmosClient(endpointUri, primaryKey, options);
Partition Key
The next error relates to the partition key. You typically create your container like this:
var container = await database.CreateContainerIfNotExistsAsync(containerId, $"/{partitionkey}");
And then add data to it like this:
var response = await container.CreateItemAsync<ItemType>(newItem, new PartitionKey(partitionkey));
Essentially, the rule here is this:
Whatever you specify as the partition key must exist in the payload with the exact same name.
Microsoft.Azure.Cosmos.CosmosException: ‘Response status code does not indicate success: BadRequest (400); Substatus: 1001; ActivityId: 88c1895e-a23c-5812-c205-d4503555d2cd; Reason: (Message: {“Errors”:[“PartitionKey extracted from document doesn’t match the one specified in the header”]}
You can find out what it thinks you’ve set the partition key to by using the following code:
var properties = await container.ReadContainerAsync();
Console.WriteLine(properties.PartitionKeyPath);
When I say exactly, I mean it has to be the same case in the payload; so if you’re key is Item, and you supply the field item, you’ll get this error. Such a mismatch can be caused by the camel casing that we mentioned earlier!
References
https://stackoverflow.com/questions/29725561/documentdb-replacedocument-fails