Skip to content
FlexQuery.NET

FlexQuery.NET

Every dynamic API eventually reimplements the same query engine: optional filters that compose, sortable columns, paging metadata, field selection, related-data loading — each one hand-built, each one a potential injection surface. FlexQuery.NET is that engine, done once: it transforms query parameters sent by clients into secure, server-side expression trees that translate to SQL.

Why FlexQuery.NET

  • No OData dependency — powerful querying without OData's complexity, setup, and tight coupling.
  • 100% server-side — all operations translate to SQL via expression trees. Nothing is fetched and filtered in memory; there is zero client evaluation.
  • Security first — declare allowed and blocked fields per endpoint; every request is validated against your model and governance rules before any query runs.
  • Multi-format — the native DSL, FQL (SQL-inspired), and MiniOData syntaxes on the same endpoint, all parsing to one internal model.
  • Multiple providers — Entity Framework Core, Dapper, or any IQueryable source.
  • Observable — pipeline events, timing reports, and SQL previews built in.

How it works

  1. A client sends query parameters (filter, sort, page, select, …) or a JSON request model.
  2. FlexQuery parses them into a QueryOptions model using the selected query syntax.
  3. Validation checks every field and operator against your entity model and governance rules — rejected requests never reach the database.
  4. The provider (EF Core or Dapper) applies the options as expressions or generated SQL.
  5. A QueryResult<T> returns data plus paging metadata, aggregates, and cursor tokens.

The full pipeline is described in Execution Pipeline.

Package ecosystem

PackagePurpose
FlexQuery.NETCore query engine — parsing, filtering, sorting, paging, projection, validation
FlexQuery.NET.EntityFrameworkCoreAsync execution, includes, and typed DTO queries for EF Core
FlexQuery.NET.DapperSQL generation and execution for Dapper
FlexQuery.NET.AspNetCoreASP.NET Core integration with [FieldAccess] security attributes
FlexQuery.NET.DiagnosticsExecution diagnostics, timing, and observability
FlexQuery.NET.OpenApiOpenAPI/Swagger documentation for FlexQuery endpoints
FlexQuery.NET.Adapters.AgGridAG Grid Server-Side Row Model request/response adapter
FlexQuery.NET.Adapters.KendoKendo UI DataSource request adapter
FlexQuery.NET.Parsers.FqlFQL (FlexQuery Language) syntax parser
FlexQuery.NET.Parsers.MiniODataLightweight OData-compatible syntax parser

All packages target .NET 6, .NET 8, and .NET 10 (FlexQuery.NET.OpenApi targets .NET 9 and .NET 10).

The shape of an endpoint

Everything below is a complete ASP.NET Core controller — this is genuinely all it takes:

C#
using FlexQuery.NET;
using FlexQuery.NET.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

[ApiController]
[Route("api/customers")]
public sealed class CustomersController(AppDbContext db) : ControllerBase
{
    [HttpGet]
    public async Task<IActionResult> Get(
        [FromQuery] FlexQueryParameters parameters,
        CancellationToken cancellationToken)
    {
        var result = await db.Customers
            .AsNoTracking()
            .FlexQueryAsync(parameters, cancellationToken: cancellationToken);

        return Ok(result);
    }
}

From there, capability grows by configuration — governance sets, expand, aggregates, keyset paging — not by writing new endpoint code.

Where to next