I am building 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:
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.
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)