DKNet

DKNet.AspCore.Idempotency

Bounded idempotency reservations and optional response replay for .NET developers building minimal APIs.

✨ Why use it?

🚀 Quick Start

Use a .NET 10 ASP.NET Core project.

dotnet new web -f net10.0 -n PackageDemo
cd PackageDemo
dotnet add package DKNet.AspCore.Idempotency

Replace Program.cs with the example, then run dotnet run.

using DKNet.AspCore.Idempotency;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddIdempotentKey();
var app = builder.Build();
app.MapPost("/orders", () => Results.Ok(new { Accepted = true }))
    .RequiredIdempotentKey();
await app.RunAsync();

Send POST /orders with X-Idempotency-Key: order-1. The first call returns 200; an immediate retry returns 409. A missing header returns 400. This example keeps keys in one process; use a provider for shared storage.

🏗️ Architecture

A protected route uses the endpoint filter, host options and singleton store before invoking its handler.

The filter runs inside the host. The default store owns one process-local dictionary; provider registrations replace it with a singleton adapter to shared storage. Business data writes remain separate from the idempotency ledger.

🔄 How it works

The filter validates a key, reserves it, invokes a new operation, and retains eligible results; duplicates return 409 or replay.

Invalid keys return 400 before storage. A duplicate in flight always returns 409. The reservation is time-bounded, so a long-running handler can outlive it; successful completion does not create an exactly-once business transaction.

🧩 Features