Kimmel.IdMismatchEndpointFilter 1.0.0

dotnet add package Kimmel.IdMismatchEndpointFilter --version 1.0.0
                    
NuGet\Install-Package Kimmel.IdMismatchEndpointFilter -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Kimmel.IdMismatchEndpointFilter" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Kimmel.IdMismatchEndpointFilter" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Kimmel.IdMismatchEndpointFilter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Kimmel.IdMismatchEndpointFilter --version 1.0.0
                    
#r "nuget: Kimmel.IdMismatchEndpointFilter, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Kimmel.IdMismatchEndpointFilter@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Kimmel.IdMismatchEndpointFilter&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Kimmel.IdMismatchEndpointFilter&version=1.0.0
                    
Install as a Cake Tool

Id Mismatch Endpoint Filter

Backstory

A typical API endpoint address for a PUT request is something like /api/v1/people/123, where 123 is the Id of the person.

We often use FluentValidation to validate our minimal API models via an endpoint filter. In order to perform unique checks in the validator for update/edit operations, the validator needs access to the Id of the model. Below is an example constructor and unique check for a Person update validator:

public PersonUpdateValidator(IDbContextFactory<AppDbContext> dbContextFactory)
{
    RuleFor(x => x.Name)
       .NotEmpty()
       .MaxLength(50)
       .MustAsync(BeUniqueName).WithMessage("'{PropertyName}' must be unique");
}
    
protected async Task<bool> BeUniqueName(MyModel modek, string name, CancellationToken cancellationToken = default) {
    using var db = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
    return !await _context.People.Any(x => x.Name == name && x.Id != id, cancellationToken);
}

The problem is that there is nothing preventing the API consumer from using an Id of 123 in the URL, and then submitting a Person model via the request body with an Id of 456. This should result in a BadRequest response.

You could enforce this from the minimal API method like so:

group.MapPut("{id:int}", async Task<Results<BadRequest<string>, NotFound, NoContent>> (AppDbContext db, int id, PersonUpdateModel model) => {
  if (id != model.Id) 
  {
      return TypedResults.BadRequest("Id mismatch");
  }
  // ... rest of update code
}).Validate<PersonUpdateModel>();

The problem with this is that the endpoint validation filter runs before the body of the Put method. Validation with potential database queries could be happening with the wront Id value. This is not ideal.

The Solution

We created a simple endpoint filter that allows you to validate the Id of the model against the Id from the route. Using an extension method, this is what the above minimal API method would look like:

group.MapPut("{id:int}", async Task<Results<BadRequest<string>, NotFound, NoContent>> (AppDbContext db, int id, PersonUpdateModel model) => {
  
  // ... rest of update code

}).IdMismatch("id", "Id").Validate<PersonUpdateModel>();

If there is an Id mismatch, a BadRequest<string> with the default message "Id mismatch" is returned.

Usage

Usage is straight-forward, and is just two simple steps...

  1. Download the NuGet package Kimmel.IdMismatchEndpointFilter
  2. Add .IdMismatch() to the end of your PUT API method
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 181 3/15/2025