Skip to content

Commit 7fe18f2

Browse files
Merge pull request #8 from dotnet-guide-com/feature/minimal-api-pipeline-sample
Add lightweight real-world Minimal API pipeline sample
2 parents 3dba0fe + 61ef9b6 commit 7fe18f2

8 files changed

Lines changed: 1432 additions & 7 deletions

File tree

‎.github/workflows/build-samples.yml‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
- "aspnet-core/passkey-first-identity/**"
1414
- "aspnet-core/build-web-api-dotnet-8/**"
1515
- "aspnet-core/caching-outputcache-redis-invalidation/**"
16+
- "aspnet-core/minimal-apis-real-world/**"
1617
- ".github/workflows/build-samples.yml"
1718

1819
pull_request:
@@ -26,6 +27,7 @@ on:
2627
- "aspnet-core/passkey-first-identity/**"
2728
- "aspnet-core/build-web-api-dotnet-8/**"
2829
- "aspnet-core/caching-outputcache-redis-invalidation/**"
30+
- "aspnet-core/minimal-apis-real-world/**"
2931
- ".github/workflows/build-samples.yml"
3032

3133
workflow_dispatch:
@@ -319,3 +321,35 @@ jobs:
319321
aspnet-core/caching-outputcache-redis-invalidation/OutputCacheCatalogMinimal.slnx
320322
--configuration Release
321323
--no-build
324+
325+
test-minimal-api-pipeline:
326+
name: Test real-world Minimal API pipeline sample
327+
runs-on: ubuntu-latest
328+
329+
steps:
330+
- name: Check out repository
331+
uses: actions/checkout@v5
332+
333+
- name: Install .NET 10 SDK
334+
uses: actions/setup-dotnet@v5
335+
with:
336+
dotnet-version: "10.0.x"
337+
338+
- name: Restore
339+
run: >
340+
dotnet restore
341+
aspnet-core/minimal-apis-real-world/MinimalApiPipeline.slnx
342+
343+
- name: Build
344+
run: >
345+
dotnet build
346+
aspnet-core/minimal-apis-real-world/MinimalApiPipeline.slnx
347+
--configuration Release
348+
--no-restore
349+
350+
- name: Test
351+
run: >
352+
dotnet test
353+
aspnet-core/minimal-apis-real-world/MinimalApiPipeline.slnx
354+
--configuration Release
355+
--no-build

‎README.md‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Each sample folder contains a focused implementation of one tutorial topic. The
1818
| [`aspnet-core/passkey-first-identity`](aspnet-core/passkey-first-identity/) | Minimal .NET 10 Identity sample for passkey enrollment, username-first passkey sign-in, antiforgery protection, and stored credential listing | [Passkeys in ASP.NET Core Identity (.NET 10): Build a Passwordless-First Web App with WebAuthn](https://www.dotnet-guide.com/tutorials/aspnet-core/passkey-first-identity/) |
1919
| [`aspnet-core/build-web-api-dotnet-8`](aspnet-core/build-web-api-dotnet-8/) | Minimal .NET 10 Todo API demonstrating route groups, dependency injection, CRUD status codes, validation, middleware, and integration testing | [ASP.NET Core Fundamentals: Build Web APIs on .NET 8](https://www.dotnet-guide.com/tutorials/aspnet-core/build-web-api-dotnet-8/) |
2020
| [`aspnet-core/caching-outputcache-redis-invalidation`](aspnet-core/caching-outputcache-redis-invalidation/) | Minimal .NET 10 Catalog API demonstrating Output Cache policies, query and route variation, tag eviction, write-path invalidation, and integration testing | [ASP.NET Core Caching: Output Cache, Redis & Invalidation Strategies That Actually Work](https://www.dotnet-guide.com/tutorials/aspnet-core/caching-outputcache-redis-invalidation/) |
21+
| [`aspnet-core/minimal-apis-real-world`](aspnet-core/minimal-apis-real-world/) | Focused .NET 10 Orders API demonstrating endpoint filters, FluentValidation, URL-segment versioning, typed results, and partitioned rate limiting | [ASP.NET Core / Minimal APIs in the Real World: Filters, Validation, Versioning & Rate Limiting](https://www.dotnet-guide.com/tutorials/aspnet-core/minimal-apis-real-world/) |
2122

2223
## Companion articles
2324
- [Common Microsoft.Extensions.AI mistakes](https://www.dotnet-guide.com/articles/dotnet-ai/microsoft-extensions-ai-common-mistakes/)
@@ -170,17 +171,28 @@ tutorials/
170171
| | `-- TodoApiMinimal.Tests/
171172
| | |-- TodoApiMinimal.Tests.csproj
172173
| | `-- TodoApiTests.cs
173-
| `-- caching-outputcache-redis-invalidation/
174-
| |-- OutputCacheCatalogMinimal.slnx
174+
| |-- caching-outputcache-redis-invalidation/
175+
| | |-- OutputCacheCatalogMinimal.slnx
176+
| | |-- README.md
177+
| | |-- src/
178+
| | | `-- OutputCacheCatalogMinimal/
179+
| | | |-- OutputCacheCatalogMinimal.csproj
180+
| | | `-- Program.cs
181+
| | `-- tests/
182+
| | `-- OutputCacheCatalogMinimal.Tests/
183+
| | |-- OutputCacheCatalogMinimal.Tests.csproj
184+
| | `-- OutputCacheTests.cs
185+
| `-- minimal-apis-real-world/
186+
| |-- MinimalApiPipeline.slnx
175187
| |-- README.md
176188
| |-- src/
177-
| | `-- OutputCacheCatalogMinimal/
178-
| | |-- OutputCacheCatalogMinimal.csproj
189+
| | `-- MinimalApiPipeline/
190+
| | |-- MinimalApiPipeline.csproj
179191
| | `-- Program.cs
180192
| `-- tests/
181-
| `-- OutputCacheCatalogMinimal.Tests/
182-
| |-- OutputCacheCatalogMinimal.Tests.csproj
183-
| `-- OutputCacheTests.cs
193+
| `-- MinimalApiPipeline.Tests/
194+
| |-- MinimalApiPipeline.Tests.csproj
195+
| `-- MinimalApiPipelineTests.cs
184196
|-- .github/
185197
| `-- workflows/
186198
| `-- build-samples.yml
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Solution>
2+
<Folder Name="/src/">
3+
<Project Path="src/MinimalApiPipeline/MinimalApiPipeline.csproj" />
4+
</Folder>
5+
<Folder Name="/tests/">
6+
<Project Path="tests/MinimalApiPipeline.Tests/MinimalApiPipeline.Tests.csproj" />
7+
</Folder>
8+
</Solution>
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# Real-World Minimal API Pipeline
2+
3+
A focused .NET 10 companion demonstrating endpoint filters, FluentValidation,
4+
URL-segment API versioning, typed results, and partitioned rate limiting in an
5+
ASP.NET Core Minimal API.
6+
7+
## Full tutorial
8+
9+
[ASP.NET Core / Minimal APIs in the Real World: Filters, Validation, Versioning & Rate Limiting](https://www.dotnet-guide.com/tutorials/aspnet-core/minimal-apis-real-world/)
10+
11+
## Framework note
12+
13+
The tutorial explains ASP.NET Core 8.
14+
15+
This companion targets .NET 10 so it can use the DOTNET GUIDE repository's
16+
current SDK and CI toolchain. The endpoint-filter, FluentValidation,
17+
URL-versioning, typed-result, and rate-limiting patterns demonstrated here are
18+
the same core ASP.NET Core concepts.
19+
20+
## What this sample demonstrates
21+
22+
- route groups;
23+
- endpoint filters;
24+
- validation before handler execution;
25+
- RFC 7807 validation responses;
26+
- API v1 and v2 using URL segments;
27+
- different response contracts over one repository;
28+
- typed HTTP results;
29+
- a fixed-window write limiter;
30+
- independent rate-limit partitions;
31+
- integration tests with `WebApplicationFactory<Program>`.
32+
33+
## Request pipeline
34+
35+
```text
36+
request
37+
-> version selection
38+
-> rate limiting
39+
-> timing filter
40+
-> validation filter
41+
-> endpoint handler
42+
-> typed response
43+
```
44+
45+
## Versions
46+
47+
### V1
48+
49+
```text
50+
GET /api/v1/orders
51+
GET /api/v1/orders/{id}
52+
POST /api/v1/orders
53+
```
54+
55+
V1 returns item names directly.
56+
57+
### V2
58+
59+
```text
60+
GET /api/v2/orders?page=1&pageSize=2
61+
GET /api/v2/orders/{id}
62+
```
63+
64+
V2 returns a paginated envelope and exposes item counts.
65+
66+
## Demonstration rate-limit partition
67+
68+
The create endpoint permits two requests per minute for each distinct
69+
`X-Client-Id` value.
70+
71+
This header is used only to make partition behavior easy to test.
72+
73+
It is not authentication and must not be trusted as a production identity.
74+
Production partition keys should come from validated identities, API keys,
75+
tenants, or trusted network signals.
76+
77+
## Important boundary
78+
79+
This repository sample intentionally does not reproduce the complete tutorial.
80+
81+
The full tutorial also covers:
82+
83+
- JWT authentication;
84+
- scope and role authorization;
85+
- OpenAPI and Swagger;
86+
- response and output caching;
87+
- structured logging;
88+
- OpenTelemetry;
89+
- health checks;
90+
- Kestrel tuning;
91+
- Docker;
92+
- production deployment.
93+
94+
Dedicated repository companions already cover API security and Output Cache.
95+
96+
## Persistence limitation
97+
98+
Orders are stored only in process memory.
99+
100+
Restarting the application restores the three seeded orders and resets all
101+
rate-limit partitions.
102+
103+
## Prerequisite
104+
105+
- .NET 10 SDK
106+
107+
Check:
108+
109+
```powershell
110+
dotnet --version
111+
```
112+
113+
## Restore, build, and test
114+
115+
```powershell
116+
dotnet restore `
117+
.\MinimalApiPipeline.slnx
118+
119+
dotnet build `
120+
.\MinimalApiPipeline.slnx `
121+
--configuration Release `
122+
--no-restore
123+
124+
dotnet test `
125+
.\MinimalApiPipeline.slnx `
126+
--configuration Release `
127+
--no-build
128+
```
129+
130+
## Run
131+
132+
```powershell
133+
dotnet run `
134+
--project .\src\MinimalApiPipeline\MinimalApiPipeline.csproj `
135+
--urls http://localhost:5136
136+
```
137+
138+
## Example valid request
139+
140+
```powershell
141+
$headers = @{
142+
"X-Client-Id" = "powershell-demo"
143+
}
144+
145+
$body = @{
146+
customerId = "customer-400"
147+
items = @(
148+
"microphone"
149+
)
150+
} | ConvertTo-Json
151+
152+
Invoke-RestMethod `
153+
-Method Post `
154+
-Uri "http://localhost:5136/api/v1/orders" `
155+
-Headers $headers `
156+
-ContentType "application/json" `
157+
-Body $body
158+
```
159+
160+
## Project structure
161+
162+
```text
163+
MinimalApiPipeline.slnx
164+
README.md
165+
src/
166+
`-- MinimalApiPipeline/
167+
|-- MinimalApiPipeline.csproj
168+
`-- Program.cs
169+
tests/
170+
`-- MinimalApiPipeline.Tests/
171+
|-- MinimalApiPipeline.Tests.csproj
172+
`-- MinimalApiPipelineTests.cs
173+
```
174+
175+
## Deliberately omitted
176+
177+
- authentication;
178+
- authorization;
179+
- Swagger;
180+
- OpenAPI generation;
181+
- caching;
182+
- database persistence;
183+
- Redis;
184+
- OpenTelemetry exporters;
185+
- Docker;
186+
- cloud deployment;
187+
- production identity partitioning.
188+
189+
These are covered by the full tutorial or another focused sample.
190+
191+
## Verification
192+
193+
- Companion target framework: .NET 10
194+
- Tutorial framework: .NET 8
195+
- External services required: none
196+
- Database required: none
197+
- API keys required: none
198+
- Expected integration tests: 8
199+
- Last reviewed: 2026-08-01
200+
201+
This sample is educational and should be reviewed and load-tested before
202+
production use.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference
11+
Include="Asp.Versioning.Http"
12+
Version="10.0.1" />
13+
14+
<PackageReference
15+
Include="FluentValidation.DependencyInjectionExtensions"
16+
Version="12.1.1" />
17+
</ItemGroup>
18+
19+
</Project>

0 commit comments

Comments
 (0)