Dynamic Filtering
Support for DSL, JQL, JSON, and indexed query-string formats. Nested AND/OR, collection predicates (any/all), and 20+ operators out of the box.
Flexible querying for .NET IQueryable — filtering, sorting, paging, projection, validation, and field-level security.
FlexQuery.NET is a query abstraction layer for .NET APIs.
It sits between your controller and your IQueryable and translates client-provided query parameters into safe, validated, server-side expressions.
It is not just a filtering helper. It handles the full query lifecycle:
HTTP Request → Parse → Validate → Filter → Sort → Page → Project → JSON ResponseThe client sends this HTTP request:
GET /api/users?filter=status:eq:active&sort=createdAt:desc&page=1&pageSize=10&select=id,name,emailYour controller handles it in 3 lines:
[HttpGet]
public async Task<IActionResult> GetUsers([FromQuery] FlexQueryParameters parameters)
{
var result = await _context.Users.FlexQueryAsync<User>(parameters, exec =>
{
exec.AllowedFields = new HashSet<string> { "id", "name", "email", "status", "createdAt" };
});
return Ok(result);
}The response:
{
"data": [
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
{ "id": 2, "name": "Bob", "email": "bob@example.com" }
],
"totalCount": 48,
"page": 1,
"pageSize": 10
}One endpoint. Full query power. Zero unsafe code.
FlexQuery.NET is designed to work at the level of abstraction that suits your use case.
| Level | Method | Use When |
|---|---|---|
| High-level (recommended) | FlexQueryAsync | You want parse + validate + execute in one call |
| Mid-level | QueryOptionsParser.Parse + manual pipeline | You need custom steps between parse and execute |
| Low-level | ApplyFilter, ApplySort, ApplyPaging, ApplySelect | You need full control over each pipeline stage |
FlexQueryParameters (HTTP DTO)
│
▼
QueryOptionsParser.Parse()
│
▼
QueryOptions (AST)
│
├── ValidateOrThrow<T>() ← Field access, operator, type checks
│
├── ApplyFilter() ← WHERE clause (expression tree)
├── ApplySort() ← ORDER BY
├── ApplyPaging() ← SKIP / TAKE
├── ApplyFilteredIncludes() ← Include pipeline (independent)
└── ApplySelect() ← Dynamic projection
│
▼
QueryResult<object>
{ data, totalCount, page, pageSize }All expression trees are translated to SQL by EF Core. No client-side evaluation.
FlexQuery.NET auto-detects the input format:
| Format | Example |
|---|---|
| DSL | filter=status:eq:active |
| JQL | query=status = "active" AND age >= 18 |
| JSON | filter={"logic":"and","filters":[{"field":"status","operator":"eq","value":"active"}]} |
| Indexed | filter[0].field=status&filter[0].operator=eq&filter[0].value=active |
| Package | Purpose |
|---|---|
FlexQuery.NET | Core library — filtering, sorting, paging, projection, validation |
FlexQuery.NET.EFCore | EF Core async execution — FlexQueryAsync, ApplyFilteredIncludes |
FlexQuery.NET.AspNetCore | ASP.NET Core integration — FieldAccessFilter, [FieldAccess] attribute |