Kimmel.IdMismatchEndpointFilter
1.0.0
dotnet add package Kimmel.IdMismatchEndpointFilter --version 1.0.0
NuGet\Install-Package Kimmel.IdMismatchEndpointFilter -Version 1.0.0
<PackageReference Include="Kimmel.IdMismatchEndpointFilter" Version="1.0.0" />
<PackageVersion Include="Kimmel.IdMismatchEndpointFilter" Version="1.0.0" />
<PackageReference Include="Kimmel.IdMismatchEndpointFilter" />
paket add Kimmel.IdMismatchEndpointFilter --version 1.0.0
#r "nuget: Kimmel.IdMismatchEndpointFilter, 1.0.0"
#:package Kimmel.IdMismatchEndpointFilter@1.0.0
#addin nuget:?package=Kimmel.IdMismatchEndpointFilter&version=1.0.0
#tool nuget:?package=Kimmel.IdMismatchEndpointFilter&version=1.0.0
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...
- Download the NuGet package
Kimmel.IdMismatchEndpointFilter - Add
.IdMismatch()to the end of your PUT API method
| Product | Versions 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. |
-
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 |