# 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!** 🚀


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flexbase.in/solution-structure/getting-started/features/crud/get-paged-list-example.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
