Skip to content

Getting Started

FlexQuery.NET is a lightweight and powerful .NET library that enables dynamic filtering, sorting, paging, and projection over IQueryable (EF Core or any LINQ provider).

Installation

Install the core package via NuGet:

bash
dotnet add package FlexQuery.NET --version 1.7.2

If you are using Entity Framework Core, install the async helpers:

bash
dotnet add package FlexQuery.NET.EFCore --version 1.7.2

Quick Start

FlexQuery.NET is designed to be drop-in ready. Below are the two primary ways to use it in your ASP.NET Core controllers.

1. Simple Usage (Direct Parsing)

Best for rapid prototyping or simple internal tools where raw query string parsing is sufficient.

csharp
using FlexQuery.NET;
using FlexQuery.NET.Parsers;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
    private readonly AppDbContext _context;

    public CustomersController(AppDbContext context) => _context = context;

    [HttpGet]
    public async Task<IActionResult> Get()
    {
        // 1. Parse raw query string into internal options
        var options = QueryOptionsParser.Parse(Request.Query);

        // 2. Apply filtering, sorting, and paging
        var customers = await _context.Customers
            .ApplyValidatedQueryOptions(options)
            .ToListAsync();

        return Ok(customers);
    }
}

Using the QueryRequest DTO is highly recommended for production APIs. It provides clean OpenAPI/Swagger documentation and allows you to enforce server-side security rules easily.

csharp
using FlexQuery.NET;
using FlexQuery.NET.Models;
using FlexQuery.NET.Parsers;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
    private readonly AppDbContext _context;

    public CustomersController(AppDbContext context) => _context = context;

    [HttpGet]
    public async Task<IActionResult> Get([FromQuery] QueryRequest request, CancellationToken ct)
    {
        // 1. Parse the safe DTO into the execution model
        var options = QueryOptionsParser.Parse(request);

        // 2. Configure server-side security rules
        options.MaxFieldDepth = 3;
        options.AllowedFields = new HashSet<string>(StringComparer.OrdinalIgnoreCase) 
        { 
            "Id", "Name", "Email", "Orders.*" 
        };

        // 3. Manual Validation (REQUIRED before ToProjectedQueryResultAsync)
        var validator = new QueryValidator();
        var validation = validator.Validate<Customer>(options);

        if (!validation.IsValid)
        {
            return BadRequest(validation.Errors);
        }

        // 4. Execution (full pipeline: filter + sort + paging + projection)
        // Returns shaped objects with paging metadata
        var results = await _context.Customers
            .ToProjectedQueryResultAsync(options, ct);

        return Ok(results);
    }
}

Try It Out

Once your controller is set up, you can start querying immediately:

  • Filter: ?filter=name:contains:john
  • Sort: ?sort=createdAt:desc
  • Page: ?page=1&pageSize=10
  • JQL: ?query=age > 20 AND status = "Active"

Released under the MIT License.