Skip to content

Commit b8955df

Browse files
committed
Update README.md for .NET 9 compatibility and enhanced OpenAPI documentation
1 parent 5b019a7 commit b8955df

File tree

1 file changed

+91
-38
lines changed

1 file changed

+91
-38
lines changed

4-minimal-api/README.md

Lines changed: 91 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Because these things are so common, the web was designed with standard commands
2020

2121
To avoid reinventing things over and over, we use some common standards for HTTP APIs. We’ve already talked about HTTP, which handles the commands and communication between clients and servers. Another important thing for HTTP APIs to do in a predictable way is to send data back and forth. The most common way to package up data now is called JSON, short for JavaScript Object Notation. It’s a neat, simple format for packaging up data, but programmers don’t want to spend time converting their information back and forth between properties and classes in their programming language and JSON. This conversion process is called serialization, and fortunately ASP.NET Core can do that for you automatically.
2222

23-
### Welcome to the internet...
23+
### Welcome to the internet
2424

2525
Another important thing to think about for server exposed to the public internet is security and authorization. Some HTTP APIs require authentication, so only clients with the right credentials can access them. Even public HTTP APIs need to handle security, to manage things like denial of service attacks and exploiting the public APIs to take over the server or get access to information they shouldn’t have. Fortunately, ASP.NET Core can handle things like this for us, too.
2626

@@ -47,12 +47,12 @@ This endpoint accepts a pizza JSON object, turns it into C#, and passes it to a
4747

4848
### Create a new Minimal API project
4949

50-
First, you need to scaffold a project. You've installed .NET 6 and you're ready to go.
50+
First, you need to scaffold a project. You've installed .NET 9 and you're ready to go.
5151

5252
1. Create a web API by running `dotnet new`:
5353

5454
```bash
55-
dotnet new web -o PizzaStore -f net6.0
55+
dotnet new web -o PizzaStore -f net9.0
5656
```
5757

5858
You should see the _PizzaStore_ directory.
@@ -88,47 +88,54 @@ Congratulations! You've created an API by using a minimal API template.
8888

8989
Use Swagger to ensure that you have a self-documenting API, where the docs change when you change the code. This also builds a really convenient web interface for your API, so you can test out the application as you build it.
9090

91-
1. Install the *Swashbuckle* package:
92-
93-
```bash
94-
dotnet add package Swashbuckle.AspNetCore
95-
```
96-
97-
1. Next, configure your project to use Swagger. Open _Program.cs_ and add replace it with the following code:
91+
1. In .NET 9, Swagger support is built in for minimal APIs! Update your _Program.cs_ file with the following code:
9892

9993
```csharp
10094
using Microsoft.OpenApi.Models;
10195

10296
var builder = WebApplication.CreateBuilder(args);
103-
97+
98+
// Add services to the container
99+
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
104100
builder.Services.AddEndpointsApiExplorer();
105-
builder.Services.AddSwaggerGen(c =>
101+
builder.Services.AddSwaggerGen(options =>
106102
{
107-
c.SwaggerDoc("v1", new OpenApiInfo { Title = "PizzaStore API", Description = "Making the Pizzas you love", Version = "v1" });
103+
options.SwaggerDoc("v1", new OpenApiInfo
104+
{
105+
Title = "PizzaStore API",
106+
Description = "Making the Pizzas you love",
107+
Version = "v1",
108+
Contact = new OpenApiContact
109+
{
110+
Name = "Pizza Support",
111+
112+
}
113+
});
108114
});
109-
115+
110116
var app = builder.Build();
111-
117+
118+
// Configure the HTTP request pipeline
112119
if (app.Environment.IsDevelopment())
113120
{
114-
app.UseDeveloperExceptionPage();
115-
app.UseSwagger();
116-
app.UseSwaggerUI(c => // UseSwaggerUI Protected by if (env.IsDevelopment())
117-
{
118-
c.SwaggerEndpoint("/swagger/v1/swagger.json", "PizzaStore API V1");
119-
});
121+
app.UseSwagger();
122+
app.UseSwaggerUI(options =>
123+
{
124+
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
125+
options.RoutePrefix = "swagger";
126+
});
120127
}
121-
128+
122129
app.MapGet("/", () => "Hello World!");
123-
130+
124131
app.Run();
125132
```
126133

127-
This is actually just adding a few lines of code:
134+
This code:
128135

129-
- The `using` statement at the top makes it easier to use the *Swashbuckle* package without having to type out long namespaces for the commands.
130-
- The two `builder.Services.Add` lines add the two services that *Swashbuckle* needs to generate the documentation.
131-
- The `UseSwagger` and `UseSwaggerUI` lines add the Swagger and Swagger UI endpoints. UseSwaggerUI is called only in development.
136+
- Adds the `AddEndpointsApiExplorer` service which is required for Swagger to discover and generate documentation for your API endpoints
137+
- Adds the `AddSwaggerGen` service to generate the OpenAPI specification for your API
138+
- Configures Swagger UI which provides an interactive UI for testing your API endpoints
132139

133140
1. Rerun the project and go to the app's address, `http://localhost:{PORT}/swagger`.
134141
@@ -217,32 +224,78 @@ Now, connect data in your API.
217224
1. Just before `app.Run()`, add the following code:
218225

219226
```csharp
220-
app.MapGet("/pizzas/{id}", (int id) => PizzaDB.GetPizza(id));
221-
app.MapGet("/pizzas", () => PizzaDB.GetPizzas());
222-
app.MapPost("/pizzas", (Pizza pizza) => PizzaDB.CreatePizza(pizza));
223-
app.MapPut("/pizzas", (Pizza pizza) => PizzaDB.UpdatePizza(pizza));
224-
app.MapDelete("/pizzas/{id}", (int id) => PizzaDB.RemovePizza(id));
227+
// Define API endpoints with OpenAPI descriptions
228+
var pizzas = app.MapGroup("/pizzas")
229+
.WithTags("Pizzas")
230+
.WithOpenApi();
231+
232+
// Get all pizzas
233+
pizzas.MapGet("/", () => PizzaDB.GetPizzas())
234+
.WithName("GetAllPizzas")
235+
.WithSummary("Get all pizzas")
236+
.WithDescription("Retrieves the complete list of available pizzas");
237+
238+
// Get pizza by ID
239+
pizzas.MapGet("/{id}", (int id) => PizzaDB.GetPizza(id))
240+
.WithName("GetPizzaById")
241+
.WithSummary("Get pizza by ID")
242+
.WithDescription("Gets a specific pizza by its unique identifier")
243+
.WithOpenApi(operation => {
244+
operation.Parameters[0].Description = "The unique identifier for the pizza";
245+
return operation;
246+
});
247+
248+
// Create a new pizza
249+
pizzas.MapPost("/", (Pizza pizza) => PizzaDB.CreatePizza(pizza))
250+
.WithName("CreatePizza")
251+
.WithSummary("Create a new pizza")
252+
.WithDescription("Adds a new pizza to the menu");
253+
254+
// Update a pizza
255+
pizzas.MapPut("/", (Pizza pizza) => PizzaDB.UpdatePizza(pizza))
256+
.WithName("UpdatePizza")
257+
.WithSummary("Update an existing pizza")
258+
.WithDescription("Updates the details of an existing pizza");
259+
260+
// Delete a pizza
261+
pizzas.MapDelete("/{id}", (int id) => PizzaDB.RemovePizza(id))
262+
.WithName("DeletePizza")
263+
.WithSummary("Delete a pizza")
264+
.WithDescription("Removes a pizza from the menu")
265+
.WithOpenApi(operation => {
266+
operation.Parameters[0].Description = "The unique identifier for the pizza to delete";
267+
return operation;
268+
});
225269
```
226270

227-
This is the actual API part of the application! As you can see, there's not a lot of code. We're just mapping the routes to code that calls into our in-memory store.
271+
This is the actual API part of the application! In .NET 9, we're improving the OpenAPI documentation by:
272+
273+
- Using `.WithTags()` to organize endpoints in the Swagger UI
274+
- Adding `.WithSummary()` and `.WithDescription()` to provide clear documentation
275+
- Using the advanced `.WithOpenApi()` overload to customize parameter descriptions
276+
- Organizing routes with `MapGroup()` for cleaner code
228277

229278
1. Run the app by using `dotnet run`:
230279

231280
```bash
232281
dotnet run
233282
```
234283

235-
1. In your browser, go to `http://localhost:{PORT}/swagger`.
236-
237-
You should see the following page rendering:
284+
1. In your browser, go to `http://localhost:{PORT}/swagger`. You should see the following page rendering:
238285

239286
![Swagger](swagger-crud.png)
240287

241-
What's great about this Swagger UI is that you can use it to test out the API. Click on any of the API endpoints to expand it, and click the `Try it out` button. You'll see a form that makes it easy to try submitting requests to the API and seeing the response.
288+
What's great about this Swagger UI is that you can:
289+
290+
- Browse all available endpoints organized by tags
291+
- See detailed documentation including summaries and descriptions
292+
- Expand any endpoint to see request parameters and response types
293+
- Try out the API directly with the "Try it out" button
294+
- Execute requests and see the actual responses without leaving the browser
242295

243296
## What's next?
244297

245-
This is a quick first look at building a backend with Minimal APIs. To go through this same example in more detail, and with more explanation, check out the [Minimal API learning path on Microsoft Learn](https://docs.microsoft.com/learn/paths/aspnet-core-minimal-api/)!
298+
This is a quick first look at building a backend with Minimal APIs in .NET 9. To learn more about the latest features in Minimal APIs and OpenAPI support, check out the [.NET 9 minimal API documentation](https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis) and [OpenAPI documents in ASP.NET Core](https://learn.microsoft.com/aspnet/core/fundamentals/openapi/using-openapi-documents).
246299

247300
In the next lesson, you'll learn about building a game with Blazor! Stay tuned!
248301

0 commit comments

Comments
 (0)