Skip to content

Real-World API Scenario

This example demonstrates a complex request combining multiple FlexQuery.NET features to power a sophisticated dashboard view.

The Scenario

We want to fetch customers whose name contains "Connelly". For each customer, we want to include their email and name, but we only want to see their cancelled orders. Furthermore, within those cancelled orders, we only want to see the items matching "Tasty Metal Pants".

The Request

http
GET /api/customers
  ?query=(name contains "Connelly")
  &pageSize=2
  &select=id,email,name,orders.id,orders.orderDate,orders.status,orders.orderItems
  &include=orders(status = "cancelled").orderItems(productName = "Tasty Metal Pants")

Breakdown:

  1. query=(name contains "Connelly"): The Root Filter. This ensures we only get customers matching this name.
  2. pageSize=2: Limits the results to 2 customers.
  3. select=id,email,name,orders.id...: The Projection. This ensures we only fetch specific columns for both the Customer and the Order objects, reducing database bandwidth.
  4. include=orders(status = "cancelled").orderItems(...): The Filtered Include.
    • It filters the orders collection to only include those with "cancelled" status.
    • It further filters the orderItems within those orders to only include "Tasty Metal Pants".

The Response

json
{
  "totalCount": 1,
  "page": 1,
  "pageSize": 2,
  "totalPages": 1,
  "data": [
    {
      "id": 42,
      "name": "John Connelly",
      "email": "j.connelly@example.com",
      "orders": [
        {
          "id": 1001,
          "orderDate": "2026-04-15T10:30:00Z",
          "status": "cancelled",
          "orderItems": [
            {
              "id": 5001,
              "productId": 101,
              "productName": "Tasty Metal Pants",
              "unitPrice": 49.99
            }
          ]
        }
      ]
    }
  ]
}

Why this is powerful

  • Efficiency: The filtering on orders and order items happens at the database level. Only one customer is returned, and their collections are already pruned.
  • Security: The select ensures that internal fields like Customer.SecretKey or Order.InternalNotes are never even fetched from the database, much less sent to the client.
  • Simplicity: This entire logic is handled by a single .ApplyValidatedQueryOptions(options) call in the controller. No complex custom repositories or manual LINQ join logic required.

Released under the MIT License.