> For the complete documentation index, see [llms.txt](https://docs.flexbase.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flexbase.in/solution-structure/getting-started/features/crud/get-paged-list-example.md).

# Get Paged List Example

## Overview

This document demonstrates the complete **Get Paged List flow** using the **GetOrders** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → Database → Response
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (Data Retrieval)
   ↓
5. Database (Data Query)
   ↓
6. AutoMapper (Data Transformation)
   ↓
7. Response (Paged Results)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `OrdersController_GetOrders.cs`

```csharp
[HttpGet()]
[Route("GetOrders")]
[ProducesResponseType(typeof(FlexiPagedList<GetOrdersDto>), 200)]
public async Task<IActionResult> GetOrders([FromQuery]GetOrdersParams parameters)
{
    return RunQueryPagedService<GetOrdersParams, GetOrdersDto>(parameters, _processOrdersService.GetOrders);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Orders/GetOrders`
* **Input**: `GetOrdersParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `FlexiPagedList<GetOrdersDto>`

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessOrdersService_GetOrders.cs`

```csharp
public FlexiPagedList<GetOrdersDto> GetOrders(GetOrdersParams @params)
{
    return _flexHost.GetFlexiQuery<GetOrders>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetOrders
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns paged list of orders

### 3. **Query Handler** - Data Retrieval

**File**: `GetOrders.cs`

```csharp
public class GetOrders : FlexiQueryPagedListBridge<Order, GetOrdersParams, GetOrdersDto, FlexAppContextBridge>
{
    protected readonly ILogger<GetOrders> _logger;
    protected GetOrdersParams _params;
    protected readonly RepoFactory _repoFactory;

    public GetOrders(ILogger<GetOrders> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual GetOrders AssignParameters(GetOrdersParams @params)
    {
        _params = @params;
        return this;
    }

    public override FlexiPagedList<GetOrdersDto> Fetch()
    {
        var projection = Build<Order>().SelectTo<GetOrdersDto>().ToList();

        var result = BuildPagedOutput(projection);

        return result;
    }

    protected override IQueryable<T> Build<T>()
    {
        _repoFactory.Init(_params);

        IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();

        //Build Your Query With All Parameters Here

        query = CreatePagedQuery<T>(query, _params.PageNumber, _params.PageSize);

        return query;
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in query building
* **Query Building**: Creates the database query with filtering and pagination
* **Data Projection**: Uses AutoMapper to project to DTOs
* **Pagination**: Applies pagination logic to the results
* **Result Building**: Creates the paged output with metadata

### 4. **Query Parameters** - Input DTO

**File**: `GetOrdersParams.cs`

```csharp
public class GetOrdersParams : PagedQueryParamsDtoBridge
{
    // Inherits pagination properties from PagedQueryParamsDtoBridge:
    // - PageNumber
    // - PageSize
    // - SortBy
    // - SortDirection
    
    // Add custom filtering parameters here
    public string CustomerId { get; set; }
    public DateTime? OrderDateFrom { get; set; }
    public DateTime? OrderDateTo { get; set; }
    public string OrderState { get; set; }
}
```

**What Happens:**

* **Pagination Support**: Inherits standard pagination properties
* **Custom Filters**: Allows filtering by customer, date range, order state
* **Query Parameters**: Automatically bound from URL query string

### 5. **Output DTO** - Data Transfer Object

**File**: `GetOrdersDto.cs`

```csharp
public partial class GetOrdersDto : DtoBridge 
{
    public string CurrentOrderState { get; set; }
    public DateTimeOffset OrderDate { get; set; }
    public string CustomerId { get; set; }
    public int TotalQty { get; set; }
    public decimal TotalAmount { get; set; }
    public ICollection<GetOrdersDto_OrderItem> OrderItems { get; set; }
}
```

**File**: `GetOrdersDto_OrderItem.cs`

```csharp
public partial class GetOrdersDto_OrderItem : DtoBridge
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public int Qty { get; set; }
    public decimal SellingPrice { get; set; }
    public decimal Amount { get; set; }
}
```

**What Happens:**

* **Data Structure**: Defines the shape of returned data
* **Nested Objects**: Includes related order items
* **Calculated Fields**: Contains computed properties like Amount

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetOrdersMapperConfiguration.cs`

```csharp
public partial class GetOrdersMapperConfiguration : FlexMapperProfile
{
    public GetOrdersMapperConfiguration() : base()
    {
        CreateMap<Order, GetOrdersDto>()
            .ForMember(o => o.CurrentOrderState, opt => opt.MapFrom(o => o.OrderState.GetType().Name)); 
        CreateMap<OrderItem, GetOrdersDto_OrderItem>()
            .ForMember(o => o.ProductName, opt => opt.MapFrom(o => o.Product.Name))
            .ForMember(o => o.Amount, opt => opt.MapFrom(o => o.SellingPrice * o.Qty)); 
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Calculated Fields**: Computes derived properties
* **Nested Mappings**: Maps related entities to nested DTOs

## Key Differences from Command Operations

### **Query vs Command Characteristics**

| Aspect                 | Query (Get Paged List) | Command (Insert/Update/Delete) |
| ---------------------- | ---------------------- | ------------------------------ |
| **Purpose**            | Data Retrieval         | Data Modification              |
| **HTTP Method**        | `GET`                  | `POST`, `PUT`, `DELETE`        |
| **Handler Type**       | Query Handler          | Command Handler                |
| **Return Type**        | `FlexiPagedList<T>`    | `CommandResult`                |
| **Database Operation** | `SELECT`               | `INSERT`, `UPDATE`, `DELETE`   |
| **Events**             | ❌ No events published  | ✅ Events published             |
| **PreBus**             | ❌ No PreBus validation | ✅ PreBus validation            |
| **State Changes**      | ❌ No state changes     | ✅ State changes                |

### **Query-Specific Features**

1. **Pagination Support**: Built-in pagination with `FlexiPagedList<T>`
2. **AutoMapper Integration**: Automatic entity-to-DTO mapping
3. **Query Building**: Flexible query construction with filtering
4. **Performance**: Optimized for data retrieval
5. **No Side Effects**: Read-only operations

### **Pagination Features**

* **PageNumber**: Current page number (1-based)
* **PageSize**: Number of items per page
* **TotalCount**: Total number of items across all pages
* **TotalPages**: Total number of pages
* **HasNextPage**: Whether there are more pages
* **HasPreviousPage**: Whether there are previous pages

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with query parameters
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Pagination** → Apply pagination logic
6. **Response** → HTTP 200 OK with paged results

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Add filtering logic here
    if (!string.IsNullOrEmpty(_params.CustomerId))
    {
        query = query.Where(o => o.CustomerId == _params.CustomerId);
    }
    
    if (_params.OrderDateFrom.HasValue)
    {
        query = query.Where(o => o.OrderDate >= _params.OrderDateFrom.Value);
    }
    
    // Apply pagination
    query = CreatePagedQuery<T>(query, _params.PageNumber, _params.PageSize);
    
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Complex filtering
    query = query.Where(o => !o.IsSoftDeleted);
    
    if (!string.IsNullOrEmpty(_params.CustomerId))
    {
        query = query.Where(o => o.CustomerId == _params.CustomerId);
    }
    
    // Date range filtering
    if (_params.OrderDateFrom.HasValue && _params.OrderDateTo.HasValue)
    {
        query = query.Where(o => o.OrderDate >= _params.OrderDateFrom.Value && 
                                o.OrderDate <= _params.OrderDateTo.Value);
    }
    
    // State filtering
    if (!string.IsNullOrEmpty(_params.OrderState))
    {
        query = query.Where(o => o.OrderState.GetType().Name == _params.OrderState);
    }
    
    // Sorting
    if (!string.IsNullOrEmpty(_params.SortBy))
    {
        switch (_params.SortBy.ToLower())
        {
            case "orderdate":
                query = _params.SortDirection == "desc" 
                    ? query.OrderByDescending(o => o.OrderDate)
                    : query.OrderBy(o => o.OrderDate);
                break;
            case "totalamount":
                query = _params.SortDirection == "desc" 
                    ? query.OrderByDescending(o => o.TotalAmount)
                    : query.OrderBy(o => o.TotalAmount);
                break;
        }
    }
    
    // Apply pagination
    query = CreatePagedQuery<T>(query, _params.PageNumber, _params.PageSize);
    
    return query;
}
```

## Key Benefits

* **Performance**: Optimized for data retrieval with pagination
* **Flexibility**: Easy to add filtering and sorting
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **Pagination**: Built-in pagination support
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetOrders example demonstrates how FlexBase enables clean, maintainable, and scalable query operations with built-in pagination, filtering, and data transformation capabilities!** 🚀
