Skip to content

Instantly share code, notes, and snippets.

@wullemsb
Created March 1, 2026 13:24
Show Gist options
  • Select an option

  • Save wullemsb/3af661ce14e49ce0d3dd6a181c301140 to your computer and use it in GitHub Desktop.

Select an option

Save wullemsb/3af661ce14e49ce0d3dd6a181c301140 to your computer and use it in GitHub Desktop.
// Parameter objects
public record ProductFilters(
[FromQuery] string? Query,
[FromQuery] string? Category,
[FromQuery] decimal? MinPrice,
[FromQuery] decimal? MaxPrice
);
public record PaginationParams(
[FromQuery] int Page = 1,
[FromQuery] int PageSize = 20
);
// You can even nest them if you want further separation
public record ProductSearchRequest(
[AsParameters] ProductFilters Filters, // ⚠️ nesting [AsParameters] is not supported
[AsParameters] PaginationParams Pagination
);
// Better: keep them flat at the handler level
app.MapGet("/products", async (
[AsParameters] ProductFilters filters,
[AsParameters] PaginationParams pagination,
ProductsDb db,
CancellationToken ct) =>
{
var query = db.Products.AsQueryable();
if (!string.IsNullOrEmpty(filters.Query))
query = query.Where(p => p.Name.Contains(filters.Query));
if (filters.Category is not null)
query = query.Where(p => p.Category == filters.Category);
if (filters.MinPrice is not null)
query = query.Where(p => p.Price >= filters.MinPrice);
if (filters.MaxPrice is not null)
query = query.Where(p => p.Price <= filters.MaxPrice);
var total = await query.CountAsync(ct);
var items = await query
.Skip((pagination.Page - 1) * pagination.PageSize)
.Take(pagination.PageSize)
.ToListAsync(ct);
return Results.Ok(new { total, items });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment