1
votes

I am building an restful API using ASP.NET Core with Cosmos DB. There's a GetItemById request that needs a partition key.

 public static async Task<T> GetItemAsync(string itemId, string name)
    {
        try
        {
            Document document =
                await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, itemId),
                    new RequestOptions() { PartitionKey = new PartitionKey(name) });

            return (T)(dynamic)document;
        }
        catch (DocumentClientException e)
        {
            if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                return null;
            }
            else
            {
                throw;
            }
        }
    }

The GetByIdAsync() function calls this GetItemAsync() method.

    [HttpGet("{itemId}")]
    public async Task<IActionResult> GetByIdAsync(string itemId, string name)
    {
        var item = await DocumentDBRepository<TodoItem>.GetItemAsync(itemId, name);
        if (item == null)
        {
            return NotFound();
        }
        return new ObjectResult(item);
    }

The URL would be http://localhost:54084/api/todo/f323307b-142f-46f3-9072-12f41cc74e87

My Azure CosmosDB container looks like this: enter image description here

But when I run this, it gave me an error with

{Microsoft.Azure.Documents.DocumentClientException: Partition key provided either doesn't correspond to definition in the collection or doesn't match partition key field values specified in the document.

2
what value are you passing in for "name"? and what is the partition key definition for the collection? - Aravind Krishna R.
@AravindKrishnaR. That's the confusing part I had. For your first question, I just passed in null for "name". For your second question, I am not sure why do we need partition key for. I was thinking if we need to get an item by its id, all we need is its id. That's why I think it would only need the id for URL. Why do we need its name? - superninja
@AravindKrishnaR. I've also added the screenshot of partition key definition above. Thanks! - superninja
In Cosmos DB, the primary key is the combination of partition key and the row key ("id"). The combination of the two uniquely identifies a row - not the "id" alone. So you need to specify the value of Name in the partition key to find the item (not null). If your app doesn't have a natural PK, then you should consider setting "/id" as the partition key (and pass the value for both id and partition key) - Aravind Krishna R.
From the screenshot, it looks like your collection doesn't have a partition key. - Chun Liu

2 Answers

6
votes

In Cosmos DB, the primary key is the combination of partition key and the row key ("id"). The combination of the two uniquely identifies a row - not the "id" alone. So you need to specify the value of Name in the partition key to find the item (not null).

If your app doesn't have a natural PK, then you should consider setting "/id" as the partition key (and pass the value for both id and partition key)

3
votes

I figured it out. The reason why I got this error is because I didn't have partition key set up in my collection. That's why I should remove

new RequestOptions() { PartitionKey = new PartitionKey(name) }

After I remove it, it is working properly.