|
2 | 2 |
|
3 | 3 | This guide explains how to use the BookStore API client library. |
4 | 4 |
|
| 5 | +> [!NOTE] |
| 6 | +> **Build-Time Generation**: Fully automatic compile-time client generation is not currently possible because .NET 9's `Microsoft.Extensions.ApiDescription.Server` requires running the application (including database connections) to generate the OpenAPI spec. We use a runtime generation approach with manual updates or optional NSwag auto-generation from the saved `openapi.json` file. |
| 7 | +
|
5 | 8 | ## Overview |
6 | 9 |
|
7 | 10 | The BookStore API client is provided as a reusable library (`BookStore.Client`) that can be used by any .NET project. |
@@ -109,28 +112,88 @@ builder.Services |
109 | 112 |
|
110 | 113 | ### When API Changes |
111 | 114 |
|
112 | | -1. **Update OpenAPI Spec**: |
| 115 | +**Workflow**: |
| 116 | + |
| 117 | +1. **Start the API**: |
| 118 | + ```bash |
| 119 | + aspire run |
| 120 | + ``` |
| 121 | + |
| 122 | +2. **Update OpenAPI Spec**: |
113 | 123 | ```bash |
114 | 124 | ./_tools/update-openapi.sh |
115 | 125 | ``` |
116 | 126 |
|
117 | | -2. **Update `IBookStoreApi.cs`** if endpoints changed: |
118 | | - - Location: `src/Client/BookStore.Client/IBookStoreApi.cs` |
| 127 | +3. **Update Client Interface** (choose one): |
| 128 | + |
| 129 | + **Option A: NSwag Auto-Generation** (optional): |
| 130 | + ```bash |
| 131 | + ./_tools/generate-client-nswag.sh |
| 132 | + ``` |
| 133 | + |
| 134 | + **Option B: Manual Update**: |
| 135 | + - Edit `src/Client/BookStore.Client/IBookStoreApi.cs` |
119 | 136 | - Add/update methods to match API changes |
120 | 137 |
|
121 | | -3. **Build and Test**: |
| 138 | +4. **Build and Test**: |
122 | 139 | ```bash |
123 | 140 | dotnet build |
124 | 141 | dotnet test |
125 | 142 | ``` |
126 | 143 |
|
127 | | -4. **Commit Changes**: |
| 144 | +5. **Commit Changes**: |
128 | 145 | ```bash |
129 | 146 | git add openapi.json src/Client/BookStore.Client/IBookStoreApi.cs |
130 | 147 | git commit -m "Update API client: [description]" |
131 | 148 | ``` |
132 | 149 |
|
133 | | -### Update Script |
| 150 | +### NSwag Auto-Generation (Optional) |
| 151 | + |
| 152 | +NSwag can automatically generate the Refit interface from the OpenAPI spec. |
| 153 | + |
| 154 | +**Install NSwag CLI**: |
| 155 | +```bash |
| 156 | +dotnet tool install --global NSwag.ConsoleCore |
| 157 | +``` |
| 158 | + |
| 159 | +**Pros**: |
| 160 | +- ✅ Automatic - generates entire interface |
| 161 | +- ✅ Consistent - always matches OpenAPI spec |
| 162 | +- ✅ Fast - one command |
| 163 | + |
| 164 | +**Cons**: |
| 165 | +- ❌ Requires NSwag CLI installed |
| 166 | +- ❌ Generates full client implementation (not just Refit interface) |
| 167 | +- ❌ Generates DTOs (conflicts with `BookStore.Shared`) |
| 168 | +- ❌ Uses Newtonsoft.Json (we use System.Text.Json) |
| 169 | +- ❌ Needs manual cleanup and conversion to Refit |
| 170 | + |
| 171 | +> [!NOTE] |
| 172 | +> NSwag's default output generates a complete client implementation with DTOs, which conflicts with our architecture where DTOs are in `BookStore.Shared`. Converting NSwag output to a clean Refit interface requires significant manual work, making the manual approach more practical for this project. |
| 173 | +
|
| 174 | +**Current Approach**: We use **manual updates** for clean, minimal code. NSwag is available as a reference tool to see what endpoints exist, but the generated code requires extensive modification. |
| 175 | + |
| 176 | +### Why Not Build-Time Generation? |
| 177 | + |
| 178 | +Build-time OpenAPI generation is not currently feasible because: |
| 179 | + |
| 180 | +1. **`Microsoft.Extensions.ApiDescription.Server` runs the application** during build |
| 181 | +2. **Requires database connection** - The app needs PostgreSQL to start |
| 182 | +3. **Infrastructure dependencies** - Marten, Wolverine, and other services must initialize |
| 183 | +4. **CI/CD complexity** - Would need database available during builds |
| 184 | + |
| 185 | +**Microsoft's Documentation** explicitly states: |
| 186 | +> "Build-time OpenAPI document generation functions by launching the app's entrypoint with a mock server implementation." |
| 187 | +
|
| 188 | +This means the entire application stack runs, including all service registrations and infrastructure dependencies. |
| 189 | + |
| 190 | +**Our Solution**: |
| 191 | +- ✅ Generate OpenAPI at **runtime** from running API |
| 192 | +- ✅ Save `openapi.json` to git (tracks API changes) |
| 193 | +- ✅ Update client **manually** or with **NSwag** from saved spec |
| 194 | +- ✅ Simple, reliable, works in all environments |
| 195 | + |
| 196 | +### Update Scripts |
134 | 197 |
|
135 | 198 | The `update-openapi.sh` script: |
136 | 199 | - Auto-detects Aspire's dynamic ports |
|
0 commit comments