Tomuke
Tomuke

Reputation: 877

.NET Core API: PartitionKey extracted from document doesn't match the one specified in the header

Background:

I am just starting out with Azure CosmosDB and trying to make use of the Entity Framework CosmosDB provider. I have created a simple API, along with Swagger API documentation, which will operate on a single entity.

So far I have done the following:

  1. Configured a new Cosmos DB database + container
  2. Registered CosmosDB into the services container in Startup.cs
  3. Configured an entity that I want to store in my new Cosmos DB container
  4. Prepared API endpoints for basic CRUD operations

Problem:

When attempting to call my POST endpoint through Swagger to create a new record in my database, I am getting the following error:

Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: BadRequest (400); Substatus: 1001; ActivityId: fe27e816-173c-433e-8699-e9e49e01b96f; Reason: (Message: {"Errors":["PartitionKey extracted from document doesn't match the one specified in the header"]}

From following tutorials and documentation, it's not obvious why I am getting this error! Any pointers in the right direction would be much appreciated!

Potentially useful snippets that might help someone diagnose where I am going wrong:

Registering Cosmos DB to the service container:

var settings = new CosmosDbOptions();

configuration.GetSection(CosmosDbOptions.SECTION_NAME)
    .Bind(settings);

services.AddDbContext<DatabaseContext>(options => 
    {
        options.UseCosmos(
            accountEndpoint: settings.EndpointUri,
            accountKey: settings.PrimaryKey,
            databaseName: settings.DatabaseName
        );
    });

Entity:

public class Client : Entity, IGuidIdentifier, IAggregateRoot
{
    public Client() : base() 
    {
        this.Id = Guid.NewGuid();
        this.ClientId = this.Id.ToString();
    }

    public string ClientId { get; private set; }

    public IrisCode IrisCode { get; private set; }

    public string Name { get; private set; }

    public Office Office { get; private set; }

    public Logo Logo { get; private set; }
}

Entity framework confgiguration for my entity:

public class ClientConfig : IEntityTypeConfiguration<Client>
{
    public void Configure(EntityTypeBuilder<Client> builder)
    {
        builder.ToContainer("Clients");
        builder.HasPartitionKey(x => x.ClientId);

        builder.HasKey(x => x.Id);

        builder.Property(x => x.Name);
        builder.Property(x => x.ClientId);
        builder.OwnsOne(x => x.IrisCode);
        builder.OwnsOne(x => x.Office);
        builder.OwnsOne(x => x.Logo);

        builder.Ignore(x => x.DomainEvents);
    }
}

Update: It seems that the following line is causing the error, however, this leaves me in a position without having my desired partition key defined..

builder.HasPartitionKey(x => x.ClientId);

Upvotes: 5

Views: 3478

Answers (2)

Gaurav
Gaurav

Reputation: 21

Same happened to me. issue was with the camel casing of properties. Fixed it using this code:

 CosmosSerializationOptions cosmosSerializationOptions = new()
 {
     PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase,
     IgnoreNullValues = true
 };

 cosmosClient = new CosmosClient(
      settings.CosmosDbConnectionString,
      new CosmosClientOptions()
      {
          ConnectionMode = ConnectionMode.Gateway,
          SerializerOptions = cosmosSerializationOptions,
          AllowBulkExecution = true
      });

Upvotes: 0

Harshita Singh
Harshita Singh

Reputation: 4870

This error (PartitionKey extracted from document doesn't match the one specified in the header) is coming because the partition key which you have set for your Cosmos DB collection is different from what you are setting here in EF: ClientId.

Pls make sure that you have the same partition key for your Collection, for eg., you can set it using C# like below:

this.Container = await this.Database.CreateContainerIfNotExistsAsync("testContainer", "/clientId");

and have the key in your document object like below:

[JsonProperty(PropertyName = "clientId")]
public string ClientId { get; set; }

Upvotes: 2

Related Questions