DATA-2: optional list params + normalize frontend's '==' Gridify operator

- GridifyParams wrapper: nullable page/pageSize/filter/orderBy so list endpoints
  work with no query params (Gridify's non-nullable int Page made [AsParameters]
  treat them as required -> 400). Defaults page=1,pageSize=20.
- Normalize incoming filter '==' -> '=' : the frontend gridify.ts emits '==' for
  equals (its convention) but Gridify's equals is '='. Safe (values are escaped;
  != >= <= =* contain no '=='). Fixes status==Active (frontend default that 500'd).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 01:00:35 +02:00
parent c937b6d5a8
commit 7627468b82
7 changed files with 39 additions and 12 deletions

View File

@@ -13,7 +13,7 @@ namespace GerbilManagerWebAPI.Endpoints
{
var group = app.MapGroup("/color-varieties").WithTags("ColorVarieties");
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.ColorVarieties.AsNoTracking().OrderBy(v => v.SortOrder)
.ToPagedResultAsync(query, ToDto)));

View File

@@ -13,7 +13,7 @@ namespace GerbilManagerWebAPI.Endpoints
{
var group = app.MapGroup("/contacts").WithTags("Contacts");
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.Contacts.AsNoTracking().ToPagedResultAsync(query, ToDto)));
group.MapGet("/{id:guid}", async Task<Results<Ok<ContactDto>, NotFound>> (Guid id, ApplicationContext db) =>

View File

@@ -13,7 +13,7 @@ namespace GerbilManagerWebAPI.Endpoints
{
var group = app.MapGroup("/enclosures").WithTags("Enclosures");
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.Enclosures.AsNoTracking().ToPagedResultAsync(query, ToDto)));
group.MapGet("/{id:guid}", async Task<Results<Ok<EnclosureDto>, NotFound>> (Guid id, ApplicationContext db) =>

View File

@@ -15,7 +15,7 @@ namespace GerbilManagerWebAPI.Endpoints
var group = app.MapGroup("/gerbils").WithTags("Gerbils");
// GET /gerbils (Gridify: filter/order/page; e.g. status==Active, litterId==…, orderBy=name)
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.Gerbils.AsNoTracking()
.ToPagedResultAsync(query, ToDto)));

View File

@@ -14,7 +14,7 @@ namespace GerbilManagerWebAPI.Endpoints
var group = app.MapGroup("/litters").WithTags("Litters");
// GET /litters (Gridify: date range + orderBy=date supported on the DateOnly column)
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.Litters.AsNoTracking().ToPagedResultAsync(query, ToDto)));
group.MapGet("/{id:guid}", async Task<Results<Ok<LitterDto>, NotFound>> (Guid id, ApplicationContext db) =>

View File

@@ -14,7 +14,7 @@ namespace GerbilManagerWebAPI.Endpoints
var group = app.MapGroup("/health-records").WithTags("HealthRecords");
// GET /health-records?filter=gerbilId==…
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.HealthRecords.AsNoTracking().ToPagedResultAsync(query, ToDto)));
group.MapGet("/{id:guid}", async Task<Results<Ok<HealthRecordDto>, NotFound>> (Guid id, ApplicationContext db) =>
@@ -66,7 +66,7 @@ namespace GerbilManagerWebAPI.Endpoints
{
var group = app.MapGroup("/weight-records").WithTags("WeightRecords");
group.MapGet("/", async ([AsParameters] GridifyQuery query, ApplicationContext db) =>
group.MapGet("/", async ([AsParameters] GridifyParams query, ApplicationContext db) =>
TypedResults.Ok(await db.WeightRecords.AsNoTracking().ToPagedResultAsync(query, ToDto)));
group.MapGet("/{id:guid}", async Task<Results<Ok<WeightRecordDto>, NotFound>> (Guid id, ApplicationContext db) =>