Parameter Components
Create reusable parameter components for query strings, path variables, headers, and cookies.
Full source
File: [pwsh/tutorial/examples/10.4-OpenAPI-Component-Parameter.ps1][10.4-OpenAPI-Component-Parameter.ps1]
<#
Sample: OpenAPI Parameter Components
Purpose: Demonstrate reusable parameter components for pagination, filtering, and sorting.
File: 10.4-OpenAPI-Component-Parameter.ps1
Notes: Shows parameter location (Query), combined parameter components, and typed responses.
#>
param(
[int]$Port = 5000,
[IPAddress]$IPAddress = [IPAddress]::Loopback
)
# --- Logging / Server ---
New-KrLogger | Add-KrSinkConsole |
Set-KrLoggerLevel -Value Debug |
Register-KrLogger -Name 'console' -SetAsDefault
$srv = New-KrServer -Name 'OpenAPI Parameter Component' -PassThru
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
# =========================================================
# TOP-LEVEL OPENAPI
# =========================================================
Add-KrOpenApiInfo -Title 'Parameter Component API' `
-Version '1.0.0' `
-Description 'Demonstrates reusable parameter components.'
# =========================================================
# COMPONENT PARAMETERS
# =========================================================
# Define reusable parameter components using class attributes
[OpenApiParameterComponent()]
class PaginationParameters {
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Page number')]
[OpenApiPropertyAttribute(Minimum = 1, Example = 1)]
[int]$page = 1
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Items per page')]
[OpenApiPropertyAttribute(Minimum = 1, Maximum = 100, Example = 20)]
[int]$limit = 20
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Sort field (name, date, price)')]
[OpenApiPropertyAttribute(Example = 'date')]
[ValidateSet('name', 'date', 'price')]
[string]$sortBy = 'date'
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Filter by category')]
[OpenApiPropertyAttribute(Example = 'electronics')]
[string]$category
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Filter by minimum price')]
[OpenApiPropertyAttribute(Format = 'double', Example = 100)]
[double]$minPrice
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Filter by maximum price')]
[OpenApiPropertyAttribute(Format = 'double', Example = 5000)]
[double]$maxPrice
}
# =========================================================
# COMPONENT SCHEMAS
# =========================================================
[OpenApiSchemaComponent()]
class ProductItem {
[OpenApiPropertyAttribute(Description = 'Product ID', Format = 'int64', Example = 1)]
[long]$id
[OpenApiPropertyAttribute(Description = 'Product name', Example = 'Laptop')]
[string]$name
[OpenApiPropertyAttribute(Description = 'Product category', Example = 'electronics')]
[string]$category
[OpenApiPropertyAttribute(Description = 'Product price', Format = 'double', Example = 999.99)]
[double]$price
}
[OpenApiSchemaComponent()]
class ProductListResponse {
[OpenApiPropertyAttribute(Description = 'Current page number', Example = 1)]
[int]$page
[OpenApiPropertyAttribute(Description = 'Items per page', Example = 20)]
[int]$limit
[OpenApiPropertyAttribute(Description = 'Total number of items', Example = 5)]
[int]$total
[OpenApiPropertyAttribute(Description = 'List of products')]
[ProductItem[]]$items
}
# =========================================================
# ROUTES / OPERATIONS
# =========================================================
Enable-KrConfiguration
Add-KrApiDocumentationRoute -DocumentType Swagger
Add-KrApiDocumentationRoute -DocumentType Redoc
<#
.SYNOPSIS
List products with filters and pagination.
.DESCRIPTION
Retrieves a paginated list of products with optional filtering and sorting.
.PARAMETER page
Page number (pagination component)
.PARAMETER limit
Items per page (pagination component)
.PARAMETER sortBy
Sort field (pagination component)
.PARAMETER category
Filter by category (filter component)
.PARAMETER minPrice
Minimum price filter (filter component)
.PARAMETER maxPrice
Maximum price filter (filter component)
#>
function listProducts {
[OpenApiPath(HttpVerb = 'get', Pattern = '/products')]
[OpenApiResponse(StatusCode = '200', Description = 'List of products', Schema = [ProductListResponse], ContentType = ('application/json', 'application/xml'))]
[OpenApiResponse(StatusCode = '400', Description = 'Invalid parameters')]
param(
[OpenApiParameterRef(ReferenceId = 'page')]
[int]$page,
[OpenApiParameterRef(ReferenceId = 'limit')]
[int]$limit,
[OpenApiParameterRef(ReferenceId = 'sortBy')]
[string]$sortBy,
[OpenApiParameterRef(ReferenceId = 'category')]
[string]$category,
[OpenApiParameterRef(ReferenceId = 'minPrice')]
[double]$minPrice,
[OpenApiParameterRef(ReferenceId = 'maxPrice')]
[double]$maxPrice
)
# Mock product data
$allProducts = @(
@{ id = 1; name = 'Laptop'; category = 'electronics'; price = 999.99 }
@{ id = 2; name = 'Mouse'; category = 'electronics'; price = 29.99 }
@{ id = 3; name = 'Keyboard'; category = 'electronics'; price = 79.99 }
@{ id = 4; name = 'Monitor'; category = 'electronics'; price = 299.99 }
@{ id = 5; name = 'Desk Lamp'; category = 'office'; price = 49.99 }
)
# Apply filters
$filtered = $allProducts
if ($category) {
$filtered = $filtered | Where-Object { $_.category -eq $category }
}
if ($minPrice) {
$filtered = $filtered | Where-Object { $_.price -ge [double]$minPrice }
}
if ($maxPrice) {
$filtered = $filtered | Where-Object { $_.price -le [double]$maxPrice }
}
# Sort
if ($sortBy -eq 'price') {
$filtered = $filtered | Sort-Object -Property price
} elseif ($sortBy -eq 'name') {
$filtered = $filtered | Sort-Object -Property name
}
# Paginate
$page = [int]$page
$limit = [int]$limit
$skip = ($page - 1) * $limit
$paged = $filtered | Select-Object -Skip $skip -First $limit
# Convert to ProductItem array
$productItems = $paged | ForEach-Object {
[ProductItem]@{
id = $_.id
name = $_.name
category = $_.category
price = $_.price
}
}
# Build typed response
$response = [ProductListResponse]@{
page = $page
limit = $limit
total = $filtered.Count
items = $productItems
}
Write-KrResponse $response -StatusCode 200
}
# =========================================================
# OPENAPI DOC ROUTE / BUILD
# =========================================================
Add-KrOpenApiRoute
# =========================================================
# RUN SERVER
# =========================================================
Start-KrServer -Server $srv -CloseLogsOnExit
Step-by-step
- Logging: Register console logger as default.
- Server: Create server named ‘OpenAPI Parameter Component’ and add endpoint.
- OpenAPI info: Add title and description.
- Parameter component: Define
PaginationParameterscomponent with page, limit, sortBy, category, minPrice, and maxPrice fields. - Schema components: Define
ProductItemschema (id, name, category, price) andProductListResponseschema (page, limit, total, items). - Configuration: Enable configuration and add Swagger/Redoc documentation routes.
- GET endpoint: Define
listProductsfunction with[OpenApiPath]attribute, reference parameters using[OpenApiParameterRef]. - Response attributes: Add
[OpenApiResponse]attributes withSchema = [ProductListResponse]for 200 status. - Filter and paginate: Apply category and price filters, sort results, paginate with page/limit.
- Typed response: Convert filtered results to
[ProductItem]array, wrap in[ProductListResponse]object. - Return response: Use
Write-KrResponseto automatically handle JSON/XML/YAML content negotiation.
Try it
# List products with pagination
curl -i "http://127.0.0.1:5000/products?page=1&limit=10"
# List with sorting
curl -i "http://127.0.0.1:5000/products?page=1&limit=10&sortBy=price"
# List with category filter
curl -i "http://127.0.0.1:5000/products?category=electronics&limit=20"
# List with price range filter
curl -i "http://127.0.0.1:5000/products?minPrice=100&maxPrice=1000"
# Combine filters and pagination
curl -i "http://127.0.0.1:5000/products?category=office&minPrice=40&maxPrice=100&page=1&limit=5&sortBy=price"
PowerShell with parameter hashtable:
$params = @{
page = 1
limit = 10
sortBy = 'price'
category = 'electronics'
}
$uri = "http://127.0.0.1:5000/products?" + ($params.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" } -join '&')
Invoke-WebRequest -Uri $uri | Select-Object StatusCode, Content
Parameter Component Attributes
[OpenApiParameterComponent()]
class PaginationParameters {
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Page number')]
[OpenApiPropertyAttribute(Minimum = 1, Example = 1)]
[int]$page
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Items per page')]
[OpenApiPropertyAttribute(Minimum = 1, Maximum = 100, Example = 20)]
[int]$limit
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Sort field (name, date, price)')]
[OpenApiPropertyAttribute(Example = 'date')]
[ValidateSet('name', 'date', 'price')]
[string]$sortBy
}
Attribute Pattern:
[OpenApiParameterComponent()]: Marks a class as a reusable parameter component.[OpenApiParameter(In = ..., Description = ...)]: Defines parameter location (Query, Path, Header, Cookie) and description.[OpenApiPropertyAttribute(...)]: Decorates properties with schema constraints (Minimum, Maximum, Format, Example).[ValidateSet(...)]: Restricts values to enumerated list; appears in OpenAPI asenum.
Usage in Functions:
function listProducts {
param(
[OpenApiParameterRef(ReferenceId = 'page')]
[int]$page = 1,
[OpenApiParameterRef(ReferenceId = 'limit')]
[int]$limit = 20
)
}
Parameter Locations
Parameters can be in different locations:
- Query:
?page=1&limit=10(most common for filtering/pagination). - Path:
/products/{productId}(dynamic route segments). - Header: Custom HTTP headers.
- Cookie: Cookie values.
Key Concepts
- Parameter Components: Define reusable query, path, header, or cookie parameters once, reference with
[OpenApiParameterRef(ReferenceId = 'paramName')]. - Attribute Layering: Combine
[OpenApiParameter](location, description) with[OpenApiPropertyAttribute](schema constraints). - Schema Components: Use
[OpenApiSchemaComponent()]classes to define response structures (ProductItem, ProductListResponse). - Typed Responses: Convert hashtables to typed PowerShell class instances for accurate OpenAPI schema documentation.
- Content Negotiation:
Write-KrResponseautomatically handles JSON, XML, YAML, and form-urlencoded based on Accept header. - Pagination: Use
pageandlimitparameters for result limiting and offset. - Filtering: Combine filter parameters to narrow results (category, price range, date range).
- Sorting: Allow clients to specify sort order via
sortByparameter. - Validation: Use constraints (Minimum, Maximum, Format) to document and validate parameter values.
Attribute Decoration Cheatsheet
| Purpose | Attribute | Usage |
|---|---|---|
| Parameter component class | [OpenApiParameterComponent()] | Marks class as reusable parameter definition |
| Parameter location | [OpenApiParameter(In = [OaParameterLocation]::Query)] | Defines where parameter appears (Query/Path/Header/Cookie) |
| Parameter reference | [OpenApiParameterRef(ReferenceId = 'name')] | References parameter component in function params |
| Schema component class | [OpenApiSchemaComponent()] | Marks class as reusable schema definition |
| Property schema | [OpenApiPropertyAttribute(...)] | Defines property constraints (Minimum, Maximum, Format, Example) |
| Route definition | [OpenApiPath(HttpVerb = 'get', Pattern = '/path')] | Maps function to HTTP endpoint |
| Response schema | [OpenApiResponse(StatusCode = '200', Schema = [ClassName])] | Documents response status and schema |
Troubleshooting
Issue: Parameter reference not found in OpenAPI spec.
- Solution: Ensure property name in
[OpenApiParameterRef(ReferenceId = 'propertyName')]matches the property name in the parameter component class.
Issue: Query parameters not being parsed correctly.
- Solution: Verify
In = [OaParameterLocation]::Queryis set on each parameter property in the component class.
Issue: Validation constraints not appearing in OpenAPI.
- Solution: Add validation using
[OpenApiPropertyAttribute(Minimum = ..., Maximum = ...)]on parameter properties.
References
- OpenApiParameterComponent
- OpenApiParameter
- OpenApiParameterRef
- OpenApiPropertyAttribute
- OpenApiSchemaComponent
- OpenApiPath
- OpenApiResponse
- Write-KrResponse
Previous / Next
Previous: RequestBody Components Next: Response Components