> 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/rest-services/get-list-example.md).

# Get List Example

## Overview

This document demonstrates the complete **Get List flow** using the **GetShippingDetails** 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. This is similar to Get Paged List but returns a simple `IEnumerable<T>` without pagination.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → RESTClient → External System
                                                                    ↓
Response ← Controller ← Service ← Query Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO → Internal DTO Mapping
   ↓
5. Response (Simple List)
```

## Step-by-Step Implementation

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

**File**: `ShippingController_GetShippingDetails.cs`

```csharp
[HttpGet()]
[Route("GetShippingDetails")]
[ProducesResponseType(typeof(IEnumerable<GetShippingDetailsDto>), 200)]
public async Task<IActionResult> GetShippingDetails([FromQuery]GetShippingDetailsParams parameters)
{
    return RunQueryListService<GetShippingDetailsParams, GetShippingDetailsDto>(
                parameters, _processShippingService.GetShippingDetails);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Shipping/GetShippingDetails`
* **Input**: `GetShippingDetailsParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `IEnumerable<GetShippingDetailsDto>`

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

**File**: `ProcessShippingService_GetShippingDetails.cs`

```csharp
public IEnumerable<GetShippingDetailsDto> GetShippingDetails(GetShippingDetailsParams @params)
{
    return _flexHost.GetFlexiQuery<GetShippingDetails>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetShippingDetails
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns simple list of shipping details for lookup

### 3. **Query Handler** - RESTClient Integration

**File**: `GetShippingDetails.cs`

```csharp
public class GetShippingDetails : FlexiQueryEnumerableBridge<Shipping, GetShippingDetailsDto>
{
    protected readonly ILogger<GetShippingDetails> _logger;
    protected GetShippingDetailsParams _params;
    protected readonly ShippingRESTClient _restClient;

    public GetShippingDetails(ILogger<GetShippingDetails> logger, ShippingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }

    public virtual GetShippingDetails AssignParameters(GetShippingDetailsParams @params)
    {
        _params = @params;
        return this;
    }

    public override IEnumerable<GetShippingDetailsDto> Fetch()
    {
        try
        {
            // Convert internal parameters to Request DTO
            GetShippingDetailsRequestDto requestParams = new GetShippingDetailsRequestDto
            {
                SearchTerm = _params.SearchTerm,
                OrderId = _params.OrderId,
                Status = _params.Status?.ToString(),
                FromDate = _params.FromDate,
                ToDate = _params.ToDate,
                Limit = _params.Limit
            };

            // Call external REST service
            var response = _restClient.GetShippingDetails(requestParams).Result;

            if (response.IsSuccessStatusCode)
            {
                var responseContent = response.Content.ReadAsStringAsync().Result;
                var responseDto = JsonConvert.DeserializeObject<GetShippingDetailsResponseDto>(responseContent);
                
                // Convert Response DTO to Internal DTO
                var result = responseDto.ShippingDetails?.Select(x => new GetShippingDetailsDto
                {
                    Id = x.Id,
                    OrderId = x.OrderId,
                    ShippingAddress = x.ShippingAddress,
                    TrackingNumber = x.TrackingNumber,
                    Status = ParseShippingStatus(x.Status),
                    StatusDescription = x.StatusDescription,
                    TotalWeight = x.TotalWeight,
                    CreatedDate = x.CreatedDate,
                    IsActive = x.IsActive
                }).ToList() ?? new List<GetShippingDetailsDto>();

                _logger.LogDebug("Shipping details retrieved successfully. Count: {Count}", result.Count);
                return result;
            }
            else
            {
                _logger.LogWarning("Failed to retrieve shipping details. Status: {StatusCode}", response.StatusCode);
                return new List<GetShippingDetailsDto>();
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving shipping details");
            return new List<GetShippingDetailsDto>();
        }
    }

    private ShippingStatus ParseShippingStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in RESTClient calls
* **Request Mapping**: Converts internal parameters to Request DTO
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Mapping**: Converts Response DTO to Internal DTO list
* **Error Handling**: Handles success/failure responses from external system
* **Data Transformation**: Applies business logic during mapping

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

**File**: `GetShippingDetailsParams.cs`

```csharp
public class GetShippingDetailsParams : DtoBridge
{
    // Add custom filtering parameters here
    public string SearchTerm { get; set; }
    public string OrderId { get; set; }
    public ShippingStatus? Status { get; set; }
    public DateTime? FromDate { get; set; }
    public DateTime? ToDate { get; set; }
    public int? Limit { get; set; }
}
```

**What Happens:**

* **Custom Filters**: Allows filtering by search term, order ID, status, date range
* **Limit Support**: Optional limit for lookup results
* **Query Parameters**: Automatically bound from URL query string

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

**File**: `GetShippingDetailsDto.cs`

```csharp
public partial class GetShippingDetailsDto : DtoBridge 
{
    public string Id { get; set; }
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public ShippingStatus Status { get; set; }
    public string StatusDescription { get; set; }
    public decimal TotalWeight { get; set; }
    public DateTime CreatedDate { get; set; }
    public bool IsActive { get; set; }
}
```

**What Happens:**

* **Lookup Data**: Contains essential fields for dropdown/lookup scenarios
* **Minimal Structure**: Only includes necessary fields for selection
* **Performance**: Lightweight DTO for fast loading

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

**File**: `GetShippingDetailsMapperConfiguration.cs`

```csharp
public partial class GetShippingDetailsMapperConfiguration : FlexMapperProfile
{
    public GetShippingDetailsMapperConfiguration() : base()
    {
        CreateMap<Shipping, GetShippingDetailsDto>()
            .ForMember(d => d.StatusDescription, opt => opt.MapFrom(s => s.Status.ToString()))
            .ForMember(d => d.IsActive, opt => opt.MapFrom(s => !s.IsSoftDeleted));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Lookup Optimization**: Maps only necessary fields for lookup scenarios

## Key Differences from Get Paged List

### **Get List vs Get Paged List Characteristics**

| Aspect                | Get List                       | Get Paged List                    |
| --------------------- | ------------------------------ | --------------------------------- |
| **Return Type**       | `IEnumerable<T>`               | `FlexiPagedList<T>`               |
| **Pagination**        | ❌ No pagination                | ✅ Built-in pagination             |
| **Use Case**          | Lookup/Dropdown                | Data grids/tables                 |
| **Performance**       | Fast for small datasets        | Optimized for large datasets      |
| **Memory Usage**      | Lower (no pagination metadata) | Higher (includes pagination info) |
| **Controller Method** | `RunQueryListService`          | `RunQueryPagedService`            |
| **Query Base**        | `FlexiQueryEnumerableBridge`   | `FlexiQueryPagedListBridge`       |

### **Get List-Specific Features**

1. **Simple List**: Returns basic `IEnumerable<T>` without pagination
2. **Lookup Optimized**: Designed for dropdown/lookup scenarios
3. **Lightweight**: Minimal data transfer for performance
4. **No Pagination**: All results returned in single response
5. **Fast Loading**: Optimized for quick data retrieval

### **Common Use Cases**

* **Dropdown Lists**: Populate dropdown controls
* **Lookup Tables**: Search and select scenarios
* **Reference Data**: Load reference data for forms
* **Auto-complete**: Provide suggestions for input fields
* **Quick Filters**: Fast filtering options

## 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. **Response** → HTTP 200 OK with simple list

### **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.SearchTerm))
    {
        query = query.Where(s => s.ShippingAddress.Contains(_params.SearchTerm) || 
                                s.TrackingNumber.Contains(_params.SearchTerm));
    }
    
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    
    if (_params.Status.HasValue)
    {
        query = query.Where(s => s.Status == _params.Status.Value);
    }
    
    // Apply limit if specified
    if (_params.Limit.HasValue)
    {
        query = query.Take(_params.Limit.Value);
    }
    
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Exclude soft deleted items
    query = query.Where(s => !s.IsSoftDeleted);
    
    // Search functionality
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        var searchTerm = _params.SearchTerm.ToLower();
        query = query.Where(s => s.ShippingAddress.ToLower().Contains(searchTerm) || 
                                s.TrackingNumber.ToLower().Contains(searchTerm) ||
                                s.OrderId.ToLower().Contains(searchTerm));
    }
    
    // Order ID filtering
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    
    // Status filtering
    if (_params.Status.HasValue)
    {
        query = query.Where(s => s.Status == _params.Status.Value);
    }
    
    // Date range filtering
    if (_params.FromDate.HasValue)
    {
        query = query.Where(s => s.CreatedDate >= _params.FromDate.Value);
    }
    
    if (_params.ToDate.HasValue)
    {
        query = query.Where(s => s.CreatedDate <= _params.ToDate.Value);
    }
    
    // Sorting for consistent results
    query = query.OrderByDescending(s => s.CreatedDate);
    
    // Apply limit for performance
    if (_params.Limit.HasValue)
    {
        query = query.Take(_params.Limit.Value);
    }
    else
    {
        // Default limit for lookup scenarios
        query = query.Take(100);
    }
    
    return query;
}
```

## Performance Considerations

### **Optimization Strategies**

1. **Limit Results**: Always apply reasonable limits for lookup scenarios
2. **Selective Fields**: Only return necessary fields in DTO
3. **Indexing**: Ensure proper database indexes on filter fields
4. **Caching**: Consider caching for frequently accessed lookup data
5. **Lazy Loading**: Use lazy loading for related entities when appropriate

### **When to Use Get List vs Get Paged List**

| Scenario                | Use Get List | Use Get Paged List |
| ----------------------- | ------------ | ------------------ |
| **Dropdown Population** | ✅ Yes        | ❌ No               |
| **Lookup Tables**       | ✅ Yes        | ❌ No               |
| **Auto-complete**       | ✅ Yes        | ❌ No               |
| **Data Grids**          | ❌ No         | ✅ Yes              |
| **Large Datasets**      | ❌ No         | ✅ Yes              |
| **Admin Interfaces**    | ❌ No         | ✅ Yes              |
| **Reporting**           | ❌ No         | ✅ Yes              |

## Key Benefits

* **Performance**: Fast loading for small datasets
* **Simplicity**: Simple list without pagination complexity
* **Lookup Optimized**: Perfect for dropdown/lookup scenarios
* **Lightweight**: Minimal data transfer
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetShippingDetails example demonstrates how FlexBase enables clean, maintainable, and scalable list operations optimized for lookup and dropdown scenarios!** 🚀
