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.