From b4e6f8d1907fe01cb3dfa60fb7698d3c3c1f51ce Mon Sep 17 00:00:00 2001 From: wadepickett Date: Thu, 25 Jun 2026 11:02:33 -0700 Subject: [PATCH 01/40] Min Web API tutorial rewrite plus app samples updates v10 --- aspnetcore/tutorials/min-web-api.md | 192 ++++++++---------- .../Program-default-before-replacing.cs | 41 ++++ .../10/add-information-dialog-18-7-1.png | Bin 0 -> 130926 bytes 3 files changed, 124 insertions(+), 109 deletions(-) create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs create mode 100644 aspnetcore/tutorials/min-web-api/static/10/add-information-dialog-18-7-1.png diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 1152b039d6f7..b3a737fcd97f 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -4,7 +4,7 @@ author: wadepickett description: Learn how to build a minimal API with ASP.NET Core. ai-usage: ai-assisted ms.author: wpickett -ms.date: 06/03/2026 +ms.date: 06/20/2026 monikerRange: '>= aspnetcore-6.0' uid: tutorials/min-web-api --- @@ -13,7 +13,6 @@ uid: tutorials/min-web-api [!INCLUDE[](~/includes/not-latest-version.md)] - By [Wade Pickett](https://github.com/wadepickett) and [Tom Dykstra](https://github.com/tdykstra) :::moniker range=">= aspnetcore-10.0" @@ -54,18 +53,15 @@ This tutorial creates the following API: * Start Visual Studio 2026 and select **Create a new project**. * In the **Create a new project** dialog: - * Enter `Empty` in the **Search for templates** search box. - * Select the **ASP.NET Core Empty** template and select **Next**. - - ![Visual Studio Create a new project](~/tutorials/min-web-api/static/10/create-new-project-empty-vs18-6-2.png) - -* Name the project *TodoApi* and select **Next**. + * Select the **ASP.NET Core Web API** project type, and select **Next**. + * Name the project *TodoApi*, and select **Next**. * In the **Additional information** dialog: - * Select **.NET 10.0 (Long Term Support)** - * Uncheck **Do not use top-level statements** - * Select **Create** + * Confirm the **Framework** is **.NET 10.0 (Long Term Support)**. + * Confirm the checkbox for **Enable OpenAPI support** is checked. + * **Uncheck** the checkbox for **Use controllers**. This checkbox is checked by default starting with Visual Studio 2026; uncheck it to create a Minimal API project instead of a controller-based one. + * Select **Create**. - ![Additional information](~/tutorials/min-web-api/static/10/add-info-vs18-6-2.png) + ![Additional information](~/tutorials/min-web-api/static/10/add-information-dialog-18-7-1.png) # [Visual Studio Code](#tab/visual-studio-code) @@ -74,7 +70,7 @@ This tutorial creates the following API: * Run the following commands: ```dotnetcli - dotnet new web -o TodoApi + dotnet new webapi -o TodoApi cd TodoApi code -r ../TodoApi ``` @@ -88,44 +84,18 @@ This tutorial creates the following API: ### Examine the code -The `Program.cs` file contains the following code: +The `Program.cs` file generated by the template contains the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todo/Program.cs" id="snippet_min"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs"::: The preceding code: * Creates a and a with preconfigured defaults. -* Creates an HTTP GET endpoint `/` that returns `Hello World!`. - -### Run the app - -# [Visual Studio](#tab/visual-studio) - - +* Registers the in-box OpenAPI document generator with `builder.Services.AddOpenApi()`. +* Maps the generated OpenAPI document at `/openapi/v1.json` with `app.MapOpenApi()`, in the Development environment only. +* Defines a sample `GET /weatherforecast` endpoint that returns five randomly generated `WeatherForecast` records. -Press Ctrl+F5 to run without the debugger. - -[!INCLUDE[](~/includes/trustCertVS22.md)] - -Visual Studio launches the [Kestrel web server](xref:fundamentals/servers/kestrel) and opens a browser window. - -`Hello World!` is displayed in the browser. The `Program.cs` file contains a minimal but complete app. - -Close the browser window. - -# [Visual Studio Code](#tab/visual-studio-code) - -[!INCLUDE[](~/includes/trustCertVSC.md)] - -In Visual Studio Code, press Ctrl+F5 (Windows) or control+F5 (macOS) to run the app without debugging. - -The default browser launches with the following URL: `https://localhost:` where `` is the randomly generated port number. - -Close the browser window. - -In Visual Studio Code, from the *Run* menu, select *Stop Debugging* or press Shift+F5 to stop the app. - ---- +In this tutorial, you'll replace the `WeatherForecast` with a new Todo sample, with endpoints to create, read, update, and delete items, backed by a model and a database. ## Add NuGet packages @@ -150,29 +120,35 @@ NuGet packages must be added to support the database and diagnostics used in thi --- + + ## The model and database context classes * In the project folder, create a file named `Todo.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoGroup/Todo.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs"::: The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. * Create a file named `TodoDb.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoGroup/TodoDb.cs"::: + :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs"::: The preceding code defines the *database context*, which is the main class that coordinates [Entity Framework](/ef/core/) functionality for a data model. This class derives from the class. -## Add the API code +## Replace the WeatherForecast sample with the Todo API + +The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program.cs` and a `WeatherForecast` record at the bottom of the file. The sample is just a placeholder to show the template works — replace both with the Todo endpoints below. -* Replace the contents of the `Program.cs` file with the following code: +* In `Program.cs`, replace the `WeatherForecast` sample endpoint and the `WeatherForecast` record with the following code: -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_all)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_all)] + +The OpenAPI lines added by the template (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) remain in place. They now describe the Todo endpoints instead of the sample weather endpoint. The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container and enables displaying database-related exceptions: -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_DI&highlight=2-3)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_DI&highlight=2-3)] The DI container provides access to the database context and other services. @@ -182,45 +158,39 @@ This tutorial uses [Endpoints Explorer and .http files](xref:test/http-files#use # [Visual Studio Code](#tab/visual-studio-code) -## Test the web API - -There are many available web API testing tools to choose from, and you can follow this tutorial's introductory API test steps with your own preferred tool. - -This tutorial utilizes the .NET package [NSwag.AspNetCore](https://www.nuget.org/packages/NSwag.AspNetCore/), which integrates Swagger tools for generating a testing UI adhering to the OpenAPI specification: - -* NSwag: A .NET library that integrates Swagger directly into ASP.NET Core applications, providing middleware and configuration. -* Swagger: A set of open-source tools such as OpenAPIGenerator and SwaggerUI that generate API testing pages that follow the OpenAPI specification. -* OpenAPI specification: A document that describes the capabilities of the API, based on the XML and attribute annotations within the controllers and models. - -For more information on using OpenAPI and NSwag with ASP.NET, see . +### Add a browser UI to view the OpenAPI document -### Install Swagger tooling +The template already generates the OpenAPI document at `/openapi/v1.json`. To explore and test the API from a browser, add a UI that consumes that document. This tutorial uses NSwag. * Run the following command: ```dotnetcli dotnet add package NSwag.AspNetCore ``` +For more information on using OpenAPI and NSwag with ASP.NET, see . -The previous command adds the [NSwag.AspNetCore](https://www.nuget.org/packages/NSwag.AspNetCore/) package, which contains tools to generate Swagger documents and UI. -This project is using OpenAPI, so the NSwag package is only used to generate the Swagger UI. +### Add a browser UI to view the OpenAPI document -### Configure Swagger middleware +The template already generates the OpenAPI document at `/openapi/v1.json`. To explore and test the API from a browser, add a UI that consumes that document. This tutorial uses NSwag. -* In Program.cs add the following highlighted code before `app` is defined in line `var app = builder.Build();` +Add the [NSwag.AspNetCore](https://www.nuget.org/packages/NSwag.AspNetCore/) package, which provides the middleware that serves the UI: - [!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo_SwaggerVersion/Program.cs?name=snippet_swagger_add_service&highlight=7-13)] +* Run the following command: + + ```dotnetcli + dotnet add package NSwag.AspNetCore + ``` -In the previous code: +In this tutorial, NSwag is used only for its Swagger UI middleware, which reads the OpenAPI document already generated by OpenAPI. - * `builder.Services.AddEndpointsApiExplorer();`: Enables the API Explorer, which is a service that provides metadata about the HTTP API. The API Explorer is used by Swagger to generate the Swagger document. - * `builder.Services.AddOpenApiDocument(config => {...});`: Adds the Swagger OpenAPI document generator to the application services and configures it to provide more information about the API, such as its title and version. For information on providing more robust API details, see +* In `Program.cs`, add the following highlighted code inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: -* Add the following highlighted code to the next line after `app` is defined in line `var app = builder.Build();` + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_swagger_ui&highlight=3-9)] - [!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo_SwaggerVersion/Program.cs?name=snippet_swagger_enable_middleware&highlight=2-12)] + The preceding code enables the NSwag UI in Development only and points it at `/openapi/v1.json`, the document produced by `MapOpenApi()`. The UI itself is served at `/swagger`. - The previous code enables the Swagger middleware for serving the generated JSON document and the Swagger UI. Swagger is only enabled in a development environment. Enabling Swagger in a production environment could expose potentially sensitive details about the API's structure and implementation. + > [!NOTE] + > NSwag is one of several options for an OpenAPI UI. Alternatives such as [Scalar](https://www.nuget.org/packages/Scalar.AspNetCore/) or `Swashbuckle.AspNetCore.SwaggerUi` consume the same OpenAPI document and can be substituted for NSwag without changing the rest of the tutorial. @@ -230,7 +200,7 @@ In the previous code: The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` that adds data to the in-memory database: -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_post)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_post)] Run the app. The browser displays a 404 error because there's no longer a `/` endpoint. @@ -238,6 +208,8 @@ The POST endpoint will be used to add data to the app. # [Visual Studio](#tab/visual-studio) +* Press Ctrl+F5 to run the app without debugging. Visual Studio launches the [Kestrel web server](xref:fundamentals/servers/kestrel) and trusts the development certificate if needed. + * Select **View** > **Other Windows** > **Endpoints Explorer**. * Right-click the **POST** endpoint and select **Generate request**. @@ -284,8 +256,6 @@ The POST endpoint will be used to add data to the app. ### ``` -* Run the app. - * Select the **Send request** link that is above the `POST` request line. ![.http file window with run link highlighted.](~/tutorials/min-web-api/static/9.x/http-file-run-button-vs17.8.0.png) @@ -296,7 +266,7 @@ The POST endpoint will be used to add data to the app. # [Visual Studio Code](#tab/visual-studio-code) -* With the app still running, in the browser, navigate to `https://localhost:/swagger` to display the API testing page generated by Swagger. +* With the app still running, in the browser, navigate to `https://localhost:{port}/swagger` to display the API testing page generated by Swagger. ![Swagger generated API testing page](~/tutorials/min-web-api/static/9.x/swagger.png) @@ -330,7 +300,7 @@ Note a few of the useful details: ## Examine the GET endpoints -The sample app implements several GET endpoints by calling `MapGet`: +Your `Program.cs` includes a single PUT endpoint, defined with `MapPut`: |API | Description | Request body | Response body | |--- | ---- | ---- | ---- | @@ -338,7 +308,7 @@ The sample app implements several GET endpoints by calling `MapGet`: |`GET /todoitems/complete` | Get all completed to-do items | None | Array of to-do items| |`GET /todoitems/{id}` | Get an item by ID | None | To-do item| -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_get)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_get)] ## Test the GET endpoints @@ -403,7 +373,7 @@ Test the app by calling the endpoints from a browser or Swagger. * In Swagger select **GET /todoitems** > **Try it out** > **Execute**. -* Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:/todoitems`. For example, `http://localhost:5001/todoitems` +* Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems`. For example, `http://localhost:7032/todoitems` The call to `GET /todoitems` produces a response similar to the following: @@ -421,7 +391,7 @@ The call to `GET /todoitems` produces a response similar to the following: * Select **GET /todoitems** > **Try it out**. * Set the **id** field to `1` and select **Execute**. -* Alternatively, call **GET /todoitems** from a browser by entering the URI `https://localhost:/todoitems/1`. For example, `https://localhost:5001/todoitems/1` +* Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems/1`. For example, `http://localhost:7032/todoitems/1` * The response is similar to the following: @@ -450,7 +420,7 @@ The return types can represent a wide range of HTTP status codes. For example, ` The sample app implements a single PUT endpoint using `MapPut`: -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_put)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_put)] This method is similar to the `MapPost` method, except it uses HTTP PUT. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use [HTTP PATCH](xref:Microsoft.AspNetCore.Mvc.HttpPatchAttribute). @@ -458,7 +428,7 @@ This method is similar to the `MapPost` method, except it uses HTTP PUT. A succe This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call. -Update the to-do item that has `Id = 1` and set its name to `"feed fish"`. +Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. # [Visual Studio](#tab/visual-studio) @@ -514,21 +484,23 @@ Use Swagger to send a PUT request: --- -## Examine the PATCH endpoint +## Create and examine the PATCH endpoint + +A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This differs from a PUT request which replaces the entire item, so the client must send every field even to change just one. + +The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. Using nullable properties allows the endpoint to distinguish between a field that wasn't provided (null) versus a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool would default to false, potentially overwriting an existing true value when that field wasn't included in the request. Create a file named `TodoPatchDto.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todo/TodoPatchDto.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs"::: The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to distinguish between a field that wasn't provided in the request versus a field explicitly set to a value. The sample app implements a single PATCH endpoint using `MapPatch`: -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_patch)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_patch)] -This method is similar to the `MapPut` method, except it uses HTTP PATCH and only updates the fields provided in the request. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). According to the HTTP specification, a PATCH request enables partial updates, allowing clients to send only the fields that need to be changed. - -The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. Using nullable properties allows the endpoint to distinguish between a field that wasn't provided (null) versus a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool would default to false, potentially overwriting an existing true value when that field wasn't included in the request. +This method is similar to the `MapPut` method, except it uses HTTP PATCH and only updates the fields provided in the request. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). > [!NOTE] > PATCH operations allow partial updates to resources. For more advanced partial updates using JSON Patch documents, see . @@ -537,7 +509,7 @@ The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to prope This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PATCH call. Call GET to ensure there's an item in the database before making a PATCH call. -Update only the `name` property of the to-do item that has `Id = 1` and set its name to `"run errands"`. +Update only the `name` property of the Todo item that has `Id = 1` and set its name to `"run errands"`. # [Visual Studio](#tab/visual-studio) @@ -589,11 +561,13 @@ Use Swagger to send a PATCH request: --- -## Examine and test the DELETE endpoint +## Examine the DELETE endpoint + +Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: -The sample app implements a single DELETE endpoint using `MapDelete`: +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_delete)] -[!code-csharp[](~/tutorials/min-web-api/samples/9.x/todo/Program.cs?name=snippet_delete)] +## Test the DELETE endpoint # [Visual Studio](#tab/visual-studio) @@ -626,17 +600,17 @@ Use Swagger to send a DELETE request: ## Use the MapGroup API -The sample app code repeats the `todoitems` URL prefix each time it sets up an endpoint. APIs often have groups of endpoints with a common URL prefix, and the method is available to help organize such groups. It reduces repetitive code and allows for customizing entire groups of endpoints with a single call to methods like and . +The `Program.cs` you wrote repeats the `todoitems` URL prefix each time it sets up an endpoint. APIs often have groups of endpoints with a common URL prefix, and the method is available to help organize such groups. It reduces repetitive code and allows for customizing entire groups of endpoints with a single call to methods like and . Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoGroup/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs" id="snippet_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoGroup_SwaggerVersion/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs" id="snippet_all"::: --- @@ -656,25 +630,25 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoTypedResults/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoTypedResults_SwaggerVersion/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs" id="snippet_all"::: --- The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoTypedResults/Program.cs" id="snippet_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_group"::: These methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoTypedResults/Program.cs" id="snippet_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoTypedResults/Program.cs" id="snippet_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -692,11 +666,11 @@ public async Task GetAllTodos_ReturnsOkOfTodosResult() } ``` - + ## Prevent over-posting -Currently the sample app exposes the entire `Todo` object. In production applications, a subset of the model is often used to restrict the data that can be input and returned. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. **DTO** is used in this article. +Currently your API exposes the entire `Todo` object. In production applications, a subset of the model is often used to restrict the data that can be input and returned. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. **DTO** is used in this article. A DTO can be used to: @@ -707,7 +681,7 @@ A DTO can be used to: To demonstrate the DTO approach, update the `Todo` class to include a secret field: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoDTO/Todo.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs"::: The secret field needs to be hidden from this app, but an administrative app could choose to expose it. @@ -715,23 +689,23 @@ Verify you can post and get the secret field. Create a file named `TodoItemDTO.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoDTO/TodoItemDTO.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs"::: Replace the contents of the `Program.cs` file with the following code to use this DTO model: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoDTO/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs" id="snippet_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/9.x/todoDTO_SwaggerVersion/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs" id="snippet_all"::: --- Verify you can post and get all fields except the secret field. - + ## Troubleshooting with the completed sample diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs new file mode 100644 index 000000000000..ad8699de7b6b --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs @@ -0,0 +1,41 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi +builder.Services.AddOpenApi(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +app.UseHttpsRedirection(); + +var summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/weatherforecast", () => +{ + var forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; +}) +.WithName("GetWeatherForecast"); + +app.Run(); + +internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} diff --git a/aspnetcore/tutorials/min-web-api/static/10/add-information-dialog-18-7-1.png b/aspnetcore/tutorials/min-web-api/static/10/add-information-dialog-18-7-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a3c3e3bd8116da93c0262d5683e615282d1d8914 GIT binary patch literal 130926 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

(1D7ce|kiWI_KnGf?13 z7Fgo?ElTq4b;}>SZr)7&flSlX@5~5gDeY0~nH$j1HdL~AxdAuQr1*gX7Up``aBK@y}9k zDyTnjS!dJ6S8f+au=D0z@AITJ3AcqVmTh~I=3x7!EM51!e;WRqyS(xA)m|Ca*_5Ad zs&P6g3(KMlo4^3K(S!ix@%k0X4p4w2xAiE8sKMmQ^E;}<7=B^aQC8u0Zp#1rn$u@? z_OOfoYgaL%O9R&wWY#sz>ghG!v6UcEMu6yP6t6)wp2G(A&@`9j=h1x?qhG$1u9krr zO2g?cKbc4O;!opCK57KSm5Ca=A-Cf8^SjLUHM?=sukB`WDa{4u^TEh+@8W2y1u7_X z%2CrEBt!$wrp(IOU~p`r9pXwaA9V-phKxsRk3-RImu?sA@PXf>s5lWo%l6=7zpvue zxlqyR!s7Eo+N;bEK>{8qyd9a>+6~QRo)nRelt!DGI*Ec0#B@|FtPFzC>&)o+c`;hv z%~q`^bdg;;J7(A<`!#W!SnLA(=3hOW+9BjhXcWI$`;4@=F+H0I*o`P`9murJEVkj> zY1u@{0K^?`@qyAKrTcYoE}jNsa>^PxnhP5W<1V3%Ac2^fonOdXXRFH9(UyHPuaq-O zE@lbjavbI4p%F4_o7rK6gSH=q+po+rSYwd1CY*}BPpA%V{WK7Vlqt})B=g)bp{ZIpg;foRAMg1>)KU|IJ8J0GTn*cLn~uB;l@g> z2j2-+dBh*RSqd}fS%UPeLzUiE1b$JME@`*Q@>@^RatskHy>msljX$q^YWIVz509Io zrD;vD_dX|a7h!Sk4hLa^1A4JUr#!*Bk_($DRU9)`a;QaUlTd9+Zogq9w7Mnja52-1 zpX=kDIDUYMIGd|6FH490y3N7zph4#me6b_g5cP9+?r4KPjy>tVR@3tJ@BuDHCRdUX zz7D4`yD$s#$;oLv_nA9P_w}3oo^pnKr7xLgZ^1{WFd+qO1*Iy?Xq(y$ei^j95B`Y} zx5o80$zkK+0D)Ba=>5R9MXcp>-OOBl0>s2Ub!D^F2+AQ4hz_d5+75{G1Jm~|BzpFH zQGU6zyyLW&;o0m<4JotV4TvK`l-{M>4TPj_33X*gXF}cZLHyUV)srr@CYtnMg3GK( zyqzv9vC0Rz{SHW5^mHG`#UyP$sT~GoJ(uiN4MN~!jdR9*SuZl7xIjy5L)2H znC<6@>`l%+uINjv2IPdviuZNDbKRa?EmKT47W<)DjvUWoIxC(Lt3H5UaRGT}G`n*}>Lmfk(%a*ado@;gddIml!DsIs<@lFE$w;bu)(j2~5OPu0-D z4z7KmK3RS4>Lj+eKt+oz+};n}>JHMv5+c(p;$u&ZEP)`))^+IXz8zJ1|*Hb9@)iSK3~I(&0>1! z6Zn@dJq39z)}ZPp%joueR`tbB^YJm%83s=-31IPGP?6l+x~;8(IO{Rc2U*TMMbKgZ zjjRwnb*-#YX%qa!q*`Hum;%Ra6{Cj82`{IJ#I{!knDjd#366>aWiV0$*?2?}UYMhf zI#ec&*CqE6yAhcT25{z8@{igze)cY;!yybfw)o_Ki z4d$AL`*rs>q1C%d`zRa1DYD~3OD)QV%N;40Fq02H7EMkNg>LI@_BCRMY`IU-K&qr+o53Jcp8-ZX~TPu0*4v12QHNU7@;#^mC$Q#obgD` z8$H(S_j3i@!{BvEYa6sC{wHoe?{};5!fG|mA-NCJ+PfTTHI{#9X>)z3BjJ3I=*5hi za35NTZ+fD62e8qlZ!vHwe?-#&JIJWr$XVdlqq1b@_v!s9ON#62Wp3&1N)Lm-6$jbR zgPQOS93lKr)S_%PZr|@2skIiczYv7VJSN8Xv|F{U1g}#z8HWzjxK)(Wm>-j`Fu;~0 zg_oR{6yF5Im$K^}%u1r7(vD~&d_n4TiE}(RfAL#nXuoJvzwmoEr{`ezgG?|RVg?a( z58hJFoL=^sFGZwerw1zd7(uJO^ymQJxaiw1eVrFzady;3f>#JL(e zzoGp}{DV8;QL}^c(ty#m{pNGA&(U_O?>W(?{@EKHKf2LH6aK(tPFJ`tgxS?xRcfOg z)3ka%G~xQ^o56kKL;V-T;)OS)3^XUEx>|h9@w>`72hx&ToCScDgg+r{U&cz}pwiBp*L(+Q_ccJC(=-9uHX6qF8j3a6T+?777+H59h`zL9IYhrhE64^rD47?@h`*|4 z**t&T($K|vv?IV;540RcxB4S`9#wFQcX4y~jEe^^jTefR}0m;Qc@I#wYiKq(Ufx`G_(V- zxobnALTh5lHMx9z8pgd65ZY>dU`TKU!3+GzDb6huInai@8RHgL@Fqq}(#Y43H&_sv z?AI`9vJ^F`rHZZVGgdG5GqA;smZL(3Nx)6o0YtHbr#Q&QMw(utsaE-fUo43bf_oXhhqC z4kd3d==&l`ny$q&-FXhxKF)JRza9C*c*awtv?L9Wn%?4UC0u=RC-+!`RI9?Q+2#4- zEJF{U-BU4RJ|?y=qvp-YEHP`z9x@fwLfO`FYNPvGt2}_1T(hu;kO6G%|#$ zpDvsu=Di*t05=jFBrNlY#={2L?9gj~ydcCm!!t!d{BRVP@3SxA9(N`lnGF|&_q~s> z+57J&NjH4H<~}z8TnjmEo(V(d>zEE6;~vIr)XFfO_9w+fMIq90GRhahvl%<6IoE+e z9j#pRt>JjmgHwXiHE%U+8fY$g;?ZFJnH~+tNXY~UJIVxSO&HA2aYgwT_m3#WOtOc6 z*yT;QPwg{1&8m$fsar|B(&&NX>`UV+3(lHqBdsq|AMtS6M2Q;AI}gn*TKI`J9Y8?P zZifz%*`ivqV&ou-xEqu7aVsk_1766(5B^W4y0H(Q8^-ypyYaR)sqxd=n`vb}Up7jrwno&S z<1@Ak?OnU&g}pnAjRr`m(PcSWFP%VelT|rwP`GhklMzl+yTAz=Jpo+Ph-#D$D5`ID zsTZ-=6W`9LG@&%UGr(g)eagaB3riT;##vWTzyB&zz^!>En?#CdBejr^Jg551Myic< z)qLrguGC${PurG73|&msE(^j^&W!=~e}D!soYW6Ca?y-&AwCBPWDTZ6D*5sA-sKe7P3ORvDhL@vlH=x)ts+i{Je zUy{3dvVw`gm9JDMB0k=8P#Fi6wu%w0ldBf=3mKc^^hU{72<%Dz6Yy>Vg4nIHyd@a;1J6JD57_4Cwk(XY zj(W_3>1pF~;(3&f(>4q`4zFzi2L~*6V+{FRguifcn)Fz8sH+b}*# zYSQi0h2Dq9^v-VW?Pn%nWZwAZBJnqI*TwssDG4Brc^Q}#VfTN_a+>t6G_%XaK=$#V zV=yV3;@&>O#rE4n+>q&=h$m)*Lw~{jC^$olUoJT{)iMF?2AVF2hS?7dcDX=dtzLDC z)QI=3j>kLBi2F0w;$t3ruq4SMgdBy)m~Vcp)%@GMd)(%9bbucf{wvTUvSIqTrDxy* zDe235J@VkAXX5tX0dyT}@B)fyRcPm`#WGErB%vk!ij+41P)mhDm^LI%g03{9x2f zd4&D>VHA$m+qM^{niquY0?_eWDJr;*BRyLiLryX#;$wz(;El#S$7jS^fFP;)LS zyZ%{R45B|=6uqPXktT>%s)<(q`IZ$5As`m$D^}_B3fLNMq5Vs`|L(b)Uh=;tvnXAJ zmXwraVPWB~BhdQd)XNSssxf%FIV|YBPcHBbL;faVO*?mx*Vx~emAj0n)mauX7Pw5ZF{%gj}WFIkmc}gp5>pY6FBa2u?3&rsm@z2i|PrKHV zQvM4XDXFo+++(PME&}xn?!%ZtaZ0HROgr~Iu4j;1jeu^UQ_V}o=vs)*%zsGK-VF^$ zIe-BLUgo#G98m?7&jZMsQ8f5Q4;Bo7<5&R?e`GyPEf8qW6mCF8(xO9qzN2V?)^6xX ziY%6habD$5hcD!R$6-SDQ#JB3%bg4(*z`!GaIFn`Z=CM|=H!6i4PT%nXn`0!Y4Ve( zH+*?WLY~4miPg6Xi)Z`3hLps0)Bn`l|B`G(cPhfo<+k*~vH=o>ysm#(wzSA|242m% z1-X@qV=z!tKf8P}^SFkPcpTe;oPR`!i3H;-6(%H(_{$6?hl9#0P}fS3dNuXoia@Z4 zEp1*r+Ig`NVGTA|`A+chd;o5pi3Xfffxfe|0!@p~fKPvZ$9sF^W!#7`9k726EFk>? zCrV%{?$|??h-pepFC2GpB7%W6M>`fceY?B&Y-9Wt5K`zxNam1@fIN`SY3qx=2Gb^5Nvg1{!0{K%xr z6BW+48GSQ%3iYQSQ!!v}2Gw#Q&=Lj7D~gJZj*Q-R*nA@TQL=l|^s+bE)q0XIcJ7DX z-%MCaI$uzs60PW?pL%Te^CDQ8{X)@|HaT97tB^=I=Y-T;IKf#kd*42h>!Ta1D)KTk z^9w)*A0$)fEga=8enThd@dp+7LdI2N9Lt@Z?}VO_r#JzARFW!{&!!y;IQqpsY!=<| z2f!xoU=gWU7%~lSy18$Z#2~?c`HBU75T0=Kot}P$d1mk1r3x&k+lV8`JwCK3S!6s2 z!|lxJM&@##W%S_e{8)H#CM%JTfiM|-^DH|MOp<5~uUW=#!hPl6U;Mw<5(P^847eMG z926vR9iZidU)P=pKrmuEn6F;~IyWjt zqPY$qCRSZk|AwsPWQbTxg$bd>08rHvfQ;1RrwWORHu{B3o~pn8F(JOZAO_;+8bl0? zL-7`d{1NsBsNCH|GtvGh`TEIecUq8qA;YjlyA%Q@IF7~d-hpix`_W4L$Wx*dS&0mk z&_d_Z7_-`JxBPP;bEF6M*&_=)BaVN^6&ddEZg8pU$_>hbBPDsblUq|yVm9g8vCVIZ z;l7WIJYz$E|J}0wTg3K@=*`!Vt>e*!TOsZThvrH~#r>u%k&*yVjO~F)10~dbrAC0) z2Ps-uROF|3FTuPp)jBXx?%BqEjytWomv%dz&xKj7+~d=+W3+!J-CX6D6WC^^4Hm~%zCTM7Gbh&qO=_C~KriS8)3{lFD-CDV=FcPFW}!EZ%R)yUd62Nyf}W#( z8Z^)tM%ReQ;6dK<^Wc=wi`rGA8rI>0extlR;qNf`g3qyRqZEDq>9P*tHRd6NVd|lm zl55m5(qrGHpvkMOrL|fDN}D|eiWSnCiin7W+6EXOJ@>YB;>GDR$eQos10C9@JHagU2&TmV>)(nSkuKMT~W-3QdXk&-pAj3f( zTzs1ch*X2mOF+$RrTRTga4?pE*T!Vv%(BM#vgw^OIkCT2{SvzK_DJu5RhsEGfU?@` z6pbz3np;Z!AR!^ok~`d|>xn!4THSCtQYw|TFUok;H|kyCUhc)D6n|_9fxR1Ill9#jOiAC z;BL*Urmh_ksg2-{VGgryBdjmz@`}ZAJ0-!ojY}*wK%^{;m^o?kS1wB``3wVri4r#V zU5Ke}<##FlqSRnoMBfXfx0Ju_1z;5R>gdfekgbZYK@JOK>_wTzBG*1!C@Jp13%Bn& z4FW{hDe}Ui07@FXv0DiZ{f_zI;S-Q)Rb4?2-U(+GucTR-?bT0E!5> z^CL$Y>Z!qhFwjX{@M;?FK96QVZ=_HkbR2%G4mJRkN$dhRHgtTjcM!?ccCl+V0JBOs z1e7t;s~%uk`>q=e6}$$sDPIfPaGbVk^Wd|@F`+8MN@dd*=fiX*Cv$Hsx!W;v)_m{e z@H>{GedoOU#g*tEMThL4D&$HJYV%slaJUy#Oc=-ez~?oupqg(`91hivXrV?d53Bhe zFlBRbysn7+7f^&Uq+nz|Pb@AYc@PBNrCVe5OhqJtJZ9+y8No-9}ZfPQ3bUh@4b3?7GWPv@0NYAOzra>Hv*kaJ- zd`tU>urHVcR=?#Yh^v`}F-{|vl;9{y?G($Mt!&EA`e0Zv997A@NBzm`^oG!TTjM7C zQT80U-x(#Tb~==N?1v?ItW-=d|@v=YIaRRRU&3XrUEtntsA0hD3p~0 zxi}uLjq@Az5{8L5MGa5pxK6Y>{%j+JsR(j2-Uhs~4kvk3!dR&s40&EzlQ3pQU|4Y7 zl+4Hx2DC+?rru%h%5~(Yb_hhSw*|FKhv$u?pGQ#B`d(j3oEGxJ%QuA66|$mq<~tfn zea|sp_C)wbu`0VqyL?firhY~}9}9K^rf>xf#p8Ztv=$V_>fG8+E8=@P_pmuTcimrp z6)SFzW4VL#Aq-`1gMC^eI|@r(R3|>U*0G%Sj{S#xyCFkifokBo4AwzI>(K&nxCv$x zV%~BPS|4=vd;nule>p*1Pe6H4Lmfv_& z8!%hjE#6A|xb^#3_ZDAM5Alfq^DKWg1l`TSxIyOoX5Ti^0?_`v#u>leuSr!>TB_9H$_ zVeqp%3NefAAmo4e5g+ax&%g9IYRO#MWI-q9|55jrZFMcn8fb8LcZZ3)!^GVs!8N$M zdvJFM5L|=1yF+l7;10oM;+MV8x#!t?t#yCE{ai5S=<4bkRd2mjjqyw$-|2x({G!eJ z#itiVfv{B##U(#hcMJs)lfwVcD`+FqM!dXC_d6eaV0QhHEnmd$E4=2eS?+DGf6s-P zzYZN9w$q~V@DobS*CkpP%Mq_i&b;$qDp@14A{+UZnpacIM#x&(AtBFOFqtY6OZ$Qx zD4ye8LCw_F1t2S^d9PfzceG>!n;<7PtvZP;F3SUvD+S|phQmH^W`uaG7aN+VL#$kz z!TRM}Cv>mE!oz;kjTeXeh25ibczI2gfYzxO!Pts7>(Xexkr!W{PFrTJA&7LUsuE;M ziVlm+Rb@b%W7Uhmb=@4x`$qM4PE=06P~txE1~%bZ871^SmQ+Te2wfka{r92}`2b44zaYy3bTDgiojtpJ`@1ZJIe^h5b<& zOr6n$tl{$Ou8SDXZJ)W4(t3MR@b{em7RZ57vjp|nQcj2TsP`>uhW)9o4qNHK9)y!T z8l_)f@*M$m7dK%jG+Ku@Ovlq9Q-4_{p=Se`zITa@DEA-xKD{($gXzDY)PS zf4;fha4xHlmbvwmn`3uAmMfAEhjWgGEP;#0!aE3(Z!jfES)<|0&N?j&;TvDwtlGV6 z-B#4ozP^))Mo5{s_KlW0AuxP`fFQ5Iq8cQ(V^>Ml+bI#r8#kF99=#veE0%g4FihnM z4{*h#Ml}sgL?3P)vD$F+pm~}i#yfuX8+3c5{97s#02hDYdu+f*-j4E$%c*cW>O=?c z?f+C8x6>FF_sD8@ymoYCQK3~2{jc#Kd17I?Ur@}R-fkD6t6^0L-4qp(Q<)87fAG8K zH#MbJ^yM$!?@I*-H%{#rdbrRDxgn?+iIm4=W422c!PH4n@k^u{fhi|k9cRL#aP`2-=@t1==B2$8 z7V)uUJY}_)OZqnI+PEuzM7Jt5v??b4PLDGCX3T{poXw8BYh7Xq1Yr6B$#`rros0Tq z23IB;C6)}adrg7q)GwHP9-69D&AMSa%E^MGBtC9uj)KDgDdG|}!X_hHzAW!qLcWv4 z4rXvd?kmRb7nE2XNyl?AuY_Q33rmC0odF4crnc|*M5SP|02*BMk_5s~?Z+cI%B?Wg zW=I)?b19oqMD$%gt0+;J0X>ryl$qz(#>1H|e}uD=dzJU44T!ecdKb%_7xuqxg<%D( z^y7GF(zh6qg6+J^{Zm^yOgA#_SJrj*XB}0=dRG3uy@Ray_<)sq^Q7S$tk=To)il70 zDF=ShGY}~?8nS#5H-vu8Q-)AYw>6?J*}!ikPyN_1l1$~1HmnA{{5Bc&5BvmRLA^ao zUxRPY#cz+l@1%MjPii10>etB*=g#>!7yCeQkc!if?z3DNnLMJIY+VE*xaZz)x~Eu} zUrBta*eI_p*|!R8G0^AWoesGTj%UaDUO~apT*SIDpG$o^p)0RwlVAPF=MOB3Wxd;d?&)(9K`^xi=KO z|9~sXZ()=6fWKmELK1`j%~1cf_R~m_ZhWprZKUt=ZjH@CbC1%LLBgb;u2TN#<7x=* zju6O-afBZOO+`h8YG5y}8`f`>CFD>1`ufVvaDS01vFEvQ0BLd^mwhKqiTDK7HbFDc zZ~hmRY>eT!;iDO4fQy2?L!RT{sbqg!HI$7!RNIj>;+H&S-8A8M z7Znl_9>Rb%yKi$iq81|qq_5TJqBX*xN>c z-j$$sPXLNt7y?=+lw=Iz^(l*6=!<@fo+2oPS~D7d$9-@TxI4-sD#D!QMuIt`GEHx( z&pp3kes-_Mgpq2TGl!fLSuuzY1^dA00lDSex(x@&Dq)4ko}sFb@3{06H&+Ud z_Urv94R!#lLHmJ;9nuX4xP`y8;2|PF_utkG`D+R4$iVy&f_BON8$u0S%MQ5QoBZ`F zc+{jVUmAz6xx5?!2??oY?a%JVxu&wTXC0xO6qBShOEa3`J|v^pMrcG;fgJnog>D{K zHC(K=N*^T@d3r~~+?&yADXs2mI0X}4Grq=1KuSpEzxJ*P|AJ(XyyvFN%AU22tNlL&9CNdgw2RzRexCD<%+& zvcyLOSVZL4{>cBZgOo14m#exx9=_QtuiA`Ez@;(j5gNEWIT&`TelS_=(7n< z7x0_cZLrUL2|o-!$%!Gb%r^Tt%olv!Mc!5-i0gW z1dP_-knwlpm|LyQ9N;xcCl&GKhEb70V8BP^Ug0@jx}a#EnN+>~!aim3@x@SPGX?u1 zz=BZQS!)5*2>Ef?&Vrikdv6BJsK!;}sDR@gVV3O|zC+IXX(gr!drQySDs$K;B2;0y zlHTfqMa`8Z^^uh(b0-OFZ1#NGvjV8%Y}Hyywyd2xSiSQut4B_aFo+s!A~@@Ur3!pO z{QQSCtNQ0qYanEy`5}dnpyIHh1<_H~RtM-@GPOkKi9sX+nbo7XGGh2p8JO*d)x~oPn%xOLKEWgY=G0xT}!@ zPLLj2eY5jAG z1S%zZePi@YMjj0wB}2&6X@59hZ!A_JXu%Df=G_C|d?STyuPEJs?Qkqe1Tu6ZZFE%h zJW5h~!$#l|#5S^NA6j1y=E}r)3(pD-#S!X8xb~!zwJNcw<3#@e=S**!i=sxb!?}zJ z=cR3OoGKR=PLkaLCC&BSNc}!fDlN`b4c(!3BDDTDS(}sxVsNR9m0WZNn{QN;NiJ}t z*?@Y3WCdkHtw1QMfd8j-4IL^O>mkaluSqX5l7ZCuJUlBdzBvFhbv4BUKuZ~zs|S=n z$s8ip^mD0P9zk`)QOz`hq&?09OS$mS7g>;N{3^>}4r(|DZGM1d%S=_CWf6I#a|x|Jb`8%gD^ z^Q5+{GrSsdjC{x!!mB%t(&>&UeD}8bdyXa&I9eNzf2run8_L7MPLPSWNoz9Q#-bjJ z)Mly3h$9^@EXfeOj1gVb*Ywab zV{bdi3t{-DO`T%r4^?K6XOb+MZz)owA_4g|qzMiU#bkb1q_|ek@3`zXFPD(r z1Xfn~Y#=X#inayd5_onlqC_Le!RVCEU;;Ne-{+WzruQU{SvZ%aPFwN|Dd=faQXh>r>aF9%RScRs zw9)$MrUb~VK`N%G;4A4=!aQ*xNs74Z{Y2QPEAcP%5^UMyaKO&RztR1YnqO09&r73n7~?w zyL#t86t}@6Ke~>I*_{1!`V8%NbTJ$6J=vGQPt)cMAFE=?!VZ1 zuD&mr;W4?T#b1>OJd0jfqXo`QKU2p9dbcLTmIqdWBd@d8a=&p{{~Br0Il^$y>ZPSO*l zq?5N$BCPbZsN;;P9`&;8Zx{{18g@#tHZaN9YOZ3== z!Ea~WgHi}y5*`!>fSzt~$7%Atkn$+n(_i=A^abreuByxylk%#6`%~Q+R;lu^MK4EV ziD98Tl+7(gprtgGQJ(SZd!QyQSS2r6IPi02R3515BW6EW; zqs<*LIKrI92R^eb%gt4{6dACleo)r;O)se`WzHbf`w zyUMAS0owagr?K3Z8=)FkRz-y5DBB}q#mXYq3dzP}uS_r<Fy7B(yBSQwTuf|zN^zK|cJPhK`GW1=DH)H>Fmyt!;6DE%S{6XjrYya*D z^1}kRMlqIk^uqu@!X@3_>?uBz z7gxMPA;;_7NTCgwz}+jovW+EH)&THp&2_MzaBynm<^qY9 z9rH8MBV7yjZ6G5>G5+ioeigmE9`E}&-!zsZvZCESgVWxM*m%qPk8Zec2JYwosZhP?XqO^Psn1SWcm=k&;^je z^98{J;QXm%V>9R{GQaL%)Rpjt3B%*XRDlx>oLm&v5a^T1+Qv|*RYtQva<)M#lH7%* z&58rzf|K#eTzIwv9Xvo%poxQMVa)=F!;mh1wHfhf>QPmJ)(AykbDtpY^x2=lTd*NN z!nwxj+60sFk*=$%gvY-gBITkhP>|6ifyO=%0STW&Rp24*i{@6L<{!a}j;P&Qb{1wK z>>*8NavlBQwFLzp$JGdncV5DX1vOl8Y}vy-@^TlT?1m4F_ePAw{O(PzU_H@r+@Jnp zF)9xiuB+MhJUX3NC=|g+9BO*y?kmRR2fpbv9-N1%oXGDeo#C;YcL`JiaE^}D0RE=! zA401}S+&q|2qmQMW)K3&uD=bt3OO>ASIF;02@~7jr*EVUJ`VxXXPqgVAJ6Bcwu&BL z9%P{V!Gkq5W^d@&x^DiO;P!yfFTFYwrE&UnO>9t9d2T28?AQaDOrii(2jatz5R@jP zjr_uJTPO4m#S=kgCi^b@0O!YpiRHFNxbr$hhWBTi^bsUJjRB#!LOM$lG%2K(QmwD6 z;)SkyJy&;|y{9;Jxk>xNTEF4Lsv)lr=6HM!xhGu`PaCYHO;mL9JGawtH7IA5$e%dI z-fyAbI=!*#cJmVw(;{`9w16T@$OtZE1I3fSzI|4zJ!dR&$gP4`p>pNf;6lVbtt_U$H`KN2H4AeY`eXo1*M`^GYCTcrWLv_+4!d-; zOF^X>jQ(qLvr38?`PAhn>dgnhU>eM{MmNbYO7}Nz|1y|^H;e;n?RY*a;?Ap;5yh!s zn?|fhj*A*T_^U76qK!C!azU-Q(LTb@9AGB~ub&9K*Bx{cl{4EQm0A{#PJc>0R&VyT zZ>C3hs`E{)seMCnw;L?pwcR_Z>Mw*L9wIdUfuUf8G~)#jfG;d`+q!(DMg#%gh1a0e ziM>cJ{!H~3ptr#`T5o+aza;7(v6y^jo_i)xrJ{=_k0=-MB*HFVUv~@MX)f!NK=+DP~tJy6bX>~GJt?S zm>l(@z@3w0ZL+gh2)AQj;D6%)pD=L!!O2;(GW#rqIx#`ZvHM&YN5~H!O%rGAui(?RTaU%Q*L9$u|)j3;pgt1&JOAO z#jE-H%{N^~FZPH31CEOfTyHQCA5(dZ-pu>CMJv)n%HA2qt69A#eDJc}SAA1g!r0%0 z+SLgQCDqu>jZl?M4K3*w(XZ{;kya$V*D7#<4XaEA$MN!$R>wD9z=TqNvU!~GYh4u2 z-H?HUHWL@P?op|Y5(+IMRQsOa#hJT3UZw;2&pW**^opk2dxS}#Wu`pGCj zM#mjyj9%N4CcL7B5_i1w507^nvOdOwQHgg*l?FYzvYJ3w^U#g**~%&Tg&nGU4fJbW@N0gaE%d9 zcPK;tQ6Baokqn0%i@g-0d1!k?B5*K7jQlFQ?mecn6m1`UvHbetEQ%1{LaGW)-2LK^ zKJWeBa-`oraheGY3mwW2ibzM6Jwu}x`ReT2Kq{QCi$jE<<_2d|av!5ff5jMMG&06C z(Bddc+n|Cit0`Uk9a^4@2Hb=X5V-VAlb2%6@ZaOsiVg6@k*i&#zd|90?{%i5lvR3q6%7X5Bil0l0V&n@sOVh6kZmhJdQs^VM60n!ZVH&cfX{jBk<2;FrOF_xYN^?8Ml}@_aA^&Opqq z10Mf+22eQt4`)sD}| zZcs@xguYiuhg}d}5Z_oN2=8IGaptJHJh;3ybja&Q*BZ#`@fP^shQbn{H|RXRAU0@Y^1u?z|u5C7EM(q_B%hUDbS3v^HYp|cPZiLTgwJlN^@1!s!aDN!3;&!qtct^g!VRqdQ zKYH-&h>)1p3h61h4nol!uZkeNlJaYh3ln9mWhz@|M$~a`_WI{sbAyU=LV?O*1yXb~ zmSg?D$}mvninbb%X>13So7}9pmzN~4U*su22J5T6Un!+;p?O1zoyyhp2cl*PQu<)* z#0y6Q&;CKh6oS<0`=mgB4%fwYsM@jc-Uoks216m*8_%%sc)IH;;0NF z`v*#VF4Nf(%JZB&4nG>IwUFS8k*X^-UqlvFA9-1a$K7QL_v4g{LHB|rJ?U9Y3*1Vb z7jP~ln@B=%H|N){#_fRu=ubwIIYBL!2xt^1MQh&Ewf^I|4kUizAo{)U| zgtTJ$wKMV-+*HpTg_3_WTI2>haJheS%1 zU;xqNU^&65De>e-m`rX`jk@>r=32x-C^X1ck?w}7%bt?H49S;|BEQe~=-fg=O$=8L zlSU}ZTZbBfLh?|QW?}ZU%L9G^!%3zhX^me?L9Ysd$EgkdI~<)jV3C)Z6|9w&vg@0# zMY{(sf!|#4^tvU-pR{K z4(jFzw%TT&0CzW)=vF_Z>>M^U&rwmvFd3hwf-XrZ`+XD-op%beq~hWwN%2nW-GP`07qUF0UPgd`f;4QWh)`+n%a?&PSqDP z?aICfhAe+Q!`=pX0k|w#gG|QUNQ%*|JIyx-y!SbI)+mQp_IcBJS+TUBT91Ip5FraqiiWRji@cm2McK7)P@%a@n~;IgmZ&lJVeCGL^7DA~PM+JxK& zbLUaA#g=zbUTqW`v6G;baK`V*L{ywEsKdE&b&Ye-akR~tL&55F<*CRdA=oa2zmW*2 zeqdz7`}~cnXpRxzdCN?c@H@;;K6T;FWS>L#!G;qbDKaurnzAv!vs155JoW%}v{n2^ z>&uIe({q(1Nkr-RU|WqgUFkjdLL+hAP$ZBN$3>_WKFL*&@szApH=GdUz{Os{NIlwPY(MjQ&lgth3N^1*g2vWhB@8b!_5 z1>H}ijt7OfFHvD~RUMl_)b1YaXH->jm$>hZFpKzX(oWXr4{@1=>eBas6uL30w-$-IUIIBIRUz7Wd*%e1HSVptpnB^m?cass9_EPvXwKd!DTiX zk=YQnc9=)Nk*vC#a$1x?O&Uu9Cw!7C6?CcZ;Rq#3WKM%95qIP$uxJm}MIs}kog4Im z7#uXK!f;-+m;u=amW+T&qjWWCmf}{J!PP{XU|GE4!>}r>(fd;SKSdQnBF+OS1CxA~ zOsd$Gk{nv2gN9;$)s)lw4P3?wPe19Wo9x-W#vdHd9v677|59~z_yH+du2H=>VYqXp zbW&Qb=iPXdSA)=c9Jiglvf1}R^`H43IbS;R$*&V?J%mS1HM&vyD>L=jaM1@Dn!7in zG^BeCx&(DwgKa_Ii{Ra794%f2H*gjgiPuv{8pf7TdU$&1OFCOuSk`L;**1Z|)H~b% z(Leu}Un_-a$WJzA-w-qN;Kl!&tm4`C$c7l7J?du7@(Reh7=C$D zIJbiNF~&!$2UPz7OX= zN*&31z1=kdK13WA9kZUzh#wwisNZk7kvE-9ZiZ zzbNH@q&VOV)5B2o-2c?)B5&yOQLB!N#W9%pr)u^8Ul%M}wjdq+CIrGy({EAv=e^uw z0~d`#P+&rq$qhSxR%U?(h^FcNqWNo5`9BsCctwT^4@ITG6pO}mE@nPdqGXrymss$B zRo@cbGpwEUb(;BG|35!#-REOF?19ebf5|%jx0-GGu^k4X!AgI1%KzTVmd6k2rq97T z#Xnlu_=k0NBf{nU-KsyH_AvwXL;CouRq7x0k@jJ`et77>zhXN7W?OF^V0=h#zB|YL zqjfS-d{7$LD1CzdNhLiKG#}Cf_Cw4f>D;6K`Z zOZ3O77>~b%`^Ob==X^*rr?R|F{z7;7cR!f}-p83qBiqLK#}(ND!S*LE693^}*Q+4O z!^Qi;Ng<~-o(|o9z{YvcLz)E0BjaJl&uBau%`^I}A~8%0#h`Xi{pX2t7)Fa9HMs@z zzU;rdT;jJ&6v(4T4;P1qY6S7UykaqT?2N*y%VM~!Y94XaDwjpak7H_dBr0uqLiQz) zf{So>00{&(>_8B&9HX^Z#|+aK9fzUj1ON34NZ=pcT02F`0MfK1P8;b`gI#RDQ)Dt0 zhB2``)B$=_*l5wh@mwmEY+Qq&V%ekzxLe5)p4pb3q+L|d^kKY=D2dTrw=UZ3I~AVcTqWeJO_;;oJnO8>E;>-&(w0E``7AEYpeGZqqe`oL{e7_!+x_U(t~YTDTpc%sA+ zE2aU@EUFycHP^jm1{xGZH~a3)Y_bqts7_e>Y3<|hj)^#usNc(+Rn{61dULJil^w7j zSbIle{_BvfpFjrVV)R8b9yCA6{?59JI20B@>7N>0@Gfd`uFEc=ln<1&B~NqX9L%$} zERf<%2ArL^U-P?TgC*c9vNpWY6%kX53Ct#%iB@vViLV6tnOAa6h5qM}Fw}*E9dG6N z@VE2_YgJcDQ(`RXxJ+bCsL(%B5TO~+}$ob3S3 z0Ig*Ip%j)to$oz0I_wCyI-V(Z=gXm$M@uK4DSb6YI9X11^OgqV7qWh@Ru7)qc`5~S z1282m!1Y%f@c6X^-56tZBWg(Wn-LVd(Y3#UNlqM|%8YetCdv32xuk*MIX^2KGJ()EW5`UarnRML||c?7Yt zOP<_b1(5)oo`ecjpMrjx$m?_AVa#HniNyd=gY9z>{@~ny_22&_5ZL<|;$u}fsTrQw zfmoPs2_Z}zw7K%FxS!vlVc7=`r(I745^e8!F6lnX5Ck$nuxTCQhyb*$}P)RTPvywox_gGy*X%dC_QVTy_ z4b{%z6GWqhoI&uy>6fo=j`$4P=&h8+Vw2eOf0oEVW7ve2E`3BZ6wX6F>&@pX>->x) zcxJNV=y1JjOVMg?@C_>`(@RpOM4^6oJ}zAzy}p_cBNXY_a>ffdxqgGpFj|l8vAaqH zzRNY$*p{rT1YYDEmPstM^vEh?1bp;Ld67d7b6+Shg?TK&*)IIC4fL|0H!ZgsdqfDW z!b7lLYp{Oxu1n<%Xhfx0JY5ppxTZ_?lt1-8c3LPKQV7 z;n$5BAZ>2ls0g@&C&u{QHqD0q3PE->hq2(;2wmUk>!d@`saO-rBGb^zw;tQQOgg# zDltkG{ef7fo{$j9$4gf)WE>J0!ju#ubKsTHfwzwpw;dOI_b4SfaX31Q)H4 z(GPv9G9$?5LW}Tq0qx~77yB(!ODnho*CaVv!iySnkC>8RBd?(PwqgV>K-KfxROBUJ zuC4H+vXH1rlwPm3y|^-L;M>O)R4G!dLYAM*?>oX!-me%3zPG0CBLQ7}`2Q~gahQXh zKGYketa#i>W2q*^Gh<^5!31mJvvvSI3-!|D=u9hYXBMyu1=F6fn{8_g2=Ei|b`o4Q zGym!P6oPu~_>2)Af5oz6DQ-WEOjv4@+Cga|yBa?FMlU}VF4b_ZCM4`H35ymSlBeh+ zUSjhQsnR~|H)MC-Gd}cjy}+1E)hs#R5O_i2o2JX!7O9*gX}(x8Cp@*R2aW?$?l@ZT zs)b0FN(9RwB@C@?r?x~C?Vun3*4agv7(h2+HG7O;U_e>ExnW!^isZIu-ywH%yP#Z( zcrOFPrY}(F9lPWh<+G9;jMtCR^hUnuWtu}WS|GyrAs)&D=KlFJ^?^`)$Kn^?m)m_= zdChGRr&)YVvt*+tOB(#xuBfGQ8D+k;ndxJ3kAqzg20G+8lOeJ)X(TbIL8UZc^mhzZ z)CGTdsiy8&jknoIzivdnNGg;@_q>J2+B=^;fN34-pwUC_z0&EGT?r8vs{%=@*TZTq zMVd=vFC@lb&8cNq-#z2b;tx0eEd3ooL6^cU@QzG(dyr%k_LU7p*ok>V6hKD@W{DRe zEnm}T#omjWBC-iHa~j`ISefut`=Hj*!3_fFm*;(}@$*$t+%T2UxKZQ>lT6wO#_kD4UVM)= z*MmfR1(nJW^~MbZ^SgNuzn()MV(>$`jt&GI$`J-{Xzx&}D!T1dL&Bcmp>B}JajHG1 z;yDvg-5(foFd`+*K(7_pFG-ARcJxoivr>8RR%(d(W%k>PR03q+b{XycGObv47C|{| z{(hPN5h@grkpiCqxnyDEfvW{PkK2;T!<$jO?8SzQ2oJljX&aJC&KH1Pn0^zLqN!Yb zq=r3e=ET!0M;O#x)7!gjQL%k~i+Opmt9+>h%Ei<^JU$(|ZKR)o+a>tOy6&sdG2J6; zq3~jT-stZL2^bPo$95eH?fD^&I7eua{*&3Yh~?S7#O#$sfcN9-tCEL@ukKr{FB9Fr z<0J;1T!`L38LUjl;GqDcx-;=$r0(=@bz~E8b3WDg#hj0cEjPb~f$l_BLs<7o-8Tw6 zu4?f{6xl@RQTpx6`>tLyFUv{Zp=?beUO~A;`LL~N7u7U4$WB@hpsglLm6rI`yeN}~ zqFst8YX@!o3QT6=+U9}+H+Hu(Td6`9;-7!OFpIPkGV((A&xmdK(E_4ZuiDy3nRTIX zXjP1$XqeFe99|3=Dc^!iNzbHCm1`Yo#&iIIS-Jy|NJBgZj$1l3v-!f$6_&bl)$Io{0LmR>lC{dq2=}E%6m4+cUrl%dX?5uI_XM9@B9jF(LMa-;?YjQs~FETSh5C`%1)F2*+R}r|@ z8SjtAu+>|-H|O#nx&c+rK}%sF7ylVae1=7gDuc!Ae42LNHV1wE3|(=Bp`4x*1V>q? zLl%~a$Vj5adVFJ@4)lf=+tJ^4l^%_w5{u_Ks<$=-J;!yTg9@T)nA$HFJO|ff2wJp|v@wQP-3g#B z0OQl9tlmVl)+J9=8>w4Ch59}TA!b9aI;RGRHe<>-!Jpm`VH!zpVDw+L3I470b#1hN zdddgYz|RhjnkHn%uNGe6Cx?l-{LqU8W%6_RWw*X{t`H9ejqDcWhLhM-CzqCI)Fjaz1tRMHG6)ETl$s&!8J;aku{eYT^~kWr#08+};#@qomjvqT zqN@k68`pV`6V^*x*_B#)N9eopdVyiQ$`B}6CjCK)pmt35S!qMRK~Er{*{>FiX7zcS z_=*Q5jtyN!1m{N-l+X(;^-Qry`kRGUrrQ=XiH(HbHJ?Dk0dcZs&{277c!o55B!XNm zXf$j_YE<|qL1cUqI)Yja5zZtiw^-b=Na7Koa|M~I=L2Ovsq)Ly3w>uohNZoI+UX5f zkt=aH&=DJ5O*QvwxJUkrarGLEtvtg{VqyaNkyM2Wl3>IxD4C;Bl7{T(K7-;9p}3!F zSPtd_QDHb6VU{v%JXSv)fbr4!edG*2w<0{WU;SR~f#OOHsc&j5PhyhaS-6e36LPEqR6Di~O2ekk&<#+u~TJ zSbVz_aUV4DWF@B=g42D)v&cv*PS>X5Ysi0}MVfYOn2*U^r7qQ4Z}KTRwzpi^oj zpv%*L#Q7r5&)KzGeVT#0Ax{s?UNY8qzrQ{;ce{52HsWf^E%p@-=o20OpMbJn|T3)!Z+d9 zuw~E*^X1Lb#$XdPGe;Rzx^8k9FRvm<@|FL-R>JGDHTRCR+^4@5rRHrx93jk?;^>zBYBfekG>taf+IC`yN z>((Ik>>o>7`y%~h*3TuB`h97Yn81EaTp=qb)?4U(_3Nuz0{RKkE8F|0PegAr;v(we z=3hCjtWIX;7ejzQ9VmbVqDkRFP$=8AWmmASO-W!eqF|kSwI2Nx2hes*V0a-tt0N;4 z1oV9L4T(G?p5Zy82>n`di#Pt_3id+tiwx7is zl~qPcsq%1XM=6(gKi6;*NfLNAhPv#*5haDD1AfM1WkQw9DBxd^pPWqgRZ^iW?5P%J zmeqZsp_)BErmUSDW(jnx&6R>a<(KY@E8N&`VD=@J)FspH{Gsry?B~Sq_vnO_c&??m z!;QtN?kqqt3U8`UCvWlxdC27JQ@??Pk#vN36t*_epz&}aMMSU*RwK7lLT8mY!`stW z%~mVCV)H@aIafsQdu91YZzPN4!5;D2^=;IYm3$u4#ubIlQ#2*Vi5bi}hLCk>^4~DK z(T7(t3*)s;cF5?BzNM?p5IP3$5Xkq+KW;E(4&b{zdDeb9oV`{8+|7)KAn0p-te_)H zro`WxZc59^=${;T8}mHJgQHr?iBc}?`{2@Wh)<@J@b<0Ak(Mo;ML`lCRJ z0p-ZQ?XIO;d_F@@`54;{>`5Tq5YMYCqj$t`_88!h@$#ZwHN39kq$p_3bqC2fMPkIE zeO0C4T8-Z0q0?K6$YaRwCqjaEKtmViCld38Gjq}Rl4Bu$VFMN8bl#=#yk0+C$qKTB zaappN{gM<3g^Q@gELKKUdPESd`2mbdvVTYQ=aFGm&GR@yDEX=gzEFXo5Yow`yAU$K zE0O*Ra$%TLj{PS7Lw!lVn7SHiH5)&d1-h0@5EyeDRCRlTCojFfxjQ;GqM^#-~? zwn&xkPfBs?h|ZzlqXu!S_J}4F7^$)UEKF_P&@%U#_%gc{<`g#C}}}(->X2W&ujPPP&8Z4ZtKA>HHDS=(D8!jr_cSetZ+rql zWZDli!|H|tKaMweVh~GKobx2R#ERukn77gF_~HWLLw_Al);F0XuVTv^9bbuQ3Z=U? zSN0P|Gm=js3;-Vb4THnY0{@WL=!4=DM7E4}AV#B{#L;CD@%?)elKeDFB1*zue+f#6 z4+&fhL2IABf!j%N;Xbu%-=7`5V$+oGQ}LcC&JFt-wP-GSxWd-#5-T2a$3rE1oE7FP z^-{oR85_EB@v|L%59>pet4fj|10NTa@{8GJ*_0e<;g0NwrMA0Zt@117W)FF`#=*P6 zMb^fsD)-*;3Op`Tc$m<;2krdeX}eMAcd|ltkAB!O ziRau*%69T>n;(&{5iHpK7P{o~r9W|Z=wr0NFsCrJ!{x>-H9L~AJzOe7g7+w{gZaHE zs%@p-5nOBaUalPfj`7~yr-No>cOcRu*3pHL?*r)57q$*y9KRKu*RdGHy2myTB}%Mq zvU6lRBQpG!mN+5H3hjzH%f`If3CcjJ7s-KHz@9iS-lHLG8=j<4$ZlkJaLL7Lp!ex@ zyseqISa>G3KK{mwYh7uuxJDtdxxDBj$@{0#MxWG`gV64ZtX)PjeK>iubMw)Hs6oYGC%3OnoA0@;#;8;Mh-faV{8 zxXsro1fJ!YxLomQKgg$Y1&?<~Ld8gt%&7uy4&mOzL_B>L3LJq(;wBI4EjJwUq_XzB z0bJ2MNQpLYRvv-afQsRI?)+IbF!vzxjaPYIyNxKYdXfVfc;C4rWL9`yVhnf7SuJY| zH%G7>LwwudCK;a&Br!BTQ4HS8R8{8Q!`%k~-{QdAH+~RnE4ji2Gk;cl`*O-ohuA)O0Y8uR=^E8oeI~^Y!dYdCkugO3 z!9o`h$#reSrmlW_SYH@royD+bwMTn{@8Vkj{e|qDC9ad- zVDS6^+@|dTsF;Q3l0`DWB8P|=yObx;Ot|kFxAUF3O5&|fo8dtVjl^0?4MwmllX#fs zn3uWMbqlod8`OVZA71gq&@{;7=uI%gHWQ&XA=c7Pj^b&$(DIs-6KWciy<9Xnl23+5 zbh;~!NCwzgvvy72A7aQ)9d-VdHBzOv?tqIwY(XlL*Rgapn`u5RFklmtg&rCVIpfek zkokTtW20{n5#97qb2zxUrM$>z^N6|jS=OTrhAP_MQ;FX?NW%yJl;&n@#|)n80(3wx zrgfz%a1YwdpUe?sW@Y@na<>&-{y5mgt2jp?#1gr!j9GAqxAQh+$#KW}Aed=8hP*4< z4@YR@I1`}gsw!I%1C45XQAE>CSVV=WuqhB}&+<_d23X z6F-EVKN?-OAGl5?hUS;gAwO;Kr`B7JiC_!LtPwNQZsKHD(C2|~rXL`N#Qin?JWg9; zCdRrj3-d?QMy5vIsw0||TW6@oTXFvLD2d)+jYWY@hN58 zM~lHcp{~G(SndKLk*}QsF!#M~x=%M+l_|hO!bO~ve;*HFI6z=G16bAaFGUj+$4&vh zXyN4JfDkCnrehBXtxQMi`Isu&ufr{H{;0bKT?`d{`&tpJZA2~&|4&=j9SvvG#iK`y2w`^-izv}s zbczSg(*6?sqQaJ(BfryiUBT*pgXS1m^b>!ordiUL6k7F}i7=tF^sNJV_o)(@ z_8zWjxrd6Z%{9Y?)odQ_>1InKhqI7FpFC)PETLPUP3NvGpzM{+*Er zN-&iwlPfZ#p1J+quC0h7^_O#Z#*42wQ~Q9>cixmryTO}cb;JZcFb#~(T_S664}mUz zB%^b5fH&8^$;!qg0AHzPY0-sPV5Z#O0G7M1lZgfF)d$|01v-ImNf z8In!C?Jl>it*u70IIG#;3)7k1>+QnDgZRnkdmj*c?U+&~e5*~jtAYo4QC2l_+}!6E zCVKuX18Jf*&(_F~KQ?FK(&l>tPU4x!vRiXtD_soT)iXE{jPBHJ0B!qSN0dwgo_#TS ztsl>Lwlai2>p?26Mno>9?>1>w*R2Ndu-jhnnr7ZKc(8OZDYM={+qO*&`vmM0Oifva z$vCP=3PBu$icoKwCMeGah@P_T)={7NX&go6};1>K;Ks7hCK>D6Pu zIMW^u+W|D8=c;}su!Pi}C`AVm5?6P|K{>(29W*jCFu%m@{wW=VZg9Miq$}GfHrHLg z2~8St9qPYOJ;~huLHHxrllh*R!HHVMkB{5Uo`;T1#}kiN6!Ur|PM^}dZR6g7+pb5D zWi59VS&Pb}_ZsHvxT*Gq1{93GKISe00+}OtXa+gG9s1;7!U>|N&rEoy!sS>}O!N)) zc63Q%bGYPoaa>-(01xR%kC1kc$5L=1c46-sh z3lvY>zOLWeWY90VcqpM*n0sMFDride&gG+ek)y3J|}=!^JY7$ z%#l4)yVrmOC*`!?<%Z~fDr$ylMDz7fU@4@D(2hOc1P}2BmgM5I&vS4|4bRAMFom|j z+2T=*^9YiPS0n_4C}t8rTic3&hGVvnqW~0W$;EFaRqWYfJx*M#9wiW++h!6kBp$j% zrxQ__NjqPYjlWIL-qw3?V-|S6cL)R4&|4&i0rxLWq(JPKY%BP3CKHxEpUzgMIhJUcE`QK^9OzdNN zl#Nk1b{ai&Ge;`4!GP^gX*R~M>d}nhz6oTCis@JZE@S}*&9q&u?)08ZKiG7VaHO`! zy`-ITX z`@(3o{EmPrPiv^ru320%*$ZvYpA1_Rnz-{nPxI%NrF~b`%AL*(nX2YZk29@Lwbc>m zRkGqtdG7#mVQaa%nIyE#&!g6kqc$EF*DJ-)CO0~XtuL79%$ocgcoteBuQr)?_Dp&k z5L-<(eqK9~ra~4B1De=r4)nL~<;ED+-`!4d=nB=koK_-lkc`rpm3NQ#-s>uy9m;>u zuZ?aW2OxfKFEvs$E?x?OcrGKw@9&X`cs~%5xqjX1A;&T`mVn~-eaFXh-AbF84fNTO ziKytpIHj18BT}Kgab=Py23so~mr%B1;nn7NLi2>FQ5`j^fDo6dG#{oS)RSz+;mklHD7jxU6~~!?Vdq6NLhH% zhA2W~Mlqr!!~s~lkyX)v&HU58t}a;sNNAj0inlTB$<({hF{+iU9=~desNSj|Le{x} zIxekTR{W%7gI3BkC7W}DEQXqj#koaCGssCi1T!-{NMZ(#Rul(gBhVa1q0CDC=4PG;XbIR0Xtq|y z$lxIe8WF8(iv!Jh?%-seY~@pT*Y!Pzv6<(QvC)lX*dsqsZr@3iGD!CVaGW3`212a^ zn|jvS1PQ9bd`_X5t@*eCP6K$-)9_6`*uvoLVwcc$5-7j=N+rX%2kpk}P;W^w)FqVw zF)#2IFX)FXMM%gj_GI}j(6OH-Z;#t^H&z7tXmBAq>MWxcBf<^ea1qD?Sx8L9*xGSQ z1hsq<5)}3@`%!o+psf~enEUS{=sIW7U?oJ@5kUn&T0RgKn6<##dVFS`E#c{hI!8Xn zDT=pz{cicYcV_ET?-4a>=)G4;Ve}EKw~SCXvNGj-T@J?=gw?fJAc`z^ri zQqbm5A|KO5yNwYq!SSEpc0IqoT}#NM1xx-szlicU|1z=NjMx7R>9}$~a_oW76ocq^ z{mkif`K6w-sQ;Z{(J32x%oGbV8PZLvosa5qTy_{uiPETTU*)>PF6uS>O=zJ|hha)<9plXeM_IU}& ztwKr{_@~2!NY^+!5!R0+S=2HGcwRRf52d9HF{{G7{47t`Dx=bqx1UKsLTCGVOy}ZD znN;u_BogUy$%(K57LCfdDy!GW2c9~72&0RJYPMR9Sz!0#qK%UfzFZVwnF&Qc)9y<9 zxBiE-itz>!n)Z&dPwa(4A#aUC05yEWY~Ih0-YJ@{$<-Y-4X}x1WUgE``|SxT2!cKi zW|bYt@FQ3-$V9JlO^U&emtoXK4ZOf8@b#&YA;^~*p&D(8?jV`#H=h-`q($RKZd3IU zLM~pUa{DtRDDDAu>5%E#DIG7%Ra{3n3=|+^{Z>i9W^ii+u%}fyz+2_noQ3e9!LpK2ZkpxC(1@2|FO$xVSR4A#a_{04}pH&o30}MnX zt^DY#lCef`6sg~))l!8qaG$qTZXbX6>HSzK1uDQ@QRwy(d0@r zX*H2`T9m$0GZ%C7YAxalqJey2a(*@+8~EK5^Z)y16mFlpi*3&cJu3n+uh)* zFoKID7$8@W#fmpE;Anm%dFC0YM6kE}0O{gvH85OiM?VFs90xd;m3W?No!w=A>DpxI zlvfhd=jf;F_oJ*=A*^AjDQggC#uy>Kv-f2g1YI74<*OaHw3J{~Fw_Yy+@L4+ zC+gUmxLww9-Y&8@DJ!FN3y;wr2^wGQkqMe;q@lY&XUD0IK5myAcTc_7Fir+m)ysS7 z>i3i&Mob>dm!qG7rvYJGnEz=0tytpN*IrMUDfQt6@Am6EI;hPzsy+*=821AbURkKl zPfJ@p1p6q6`@++CogRiHXC0VhFk09sf|4MQv7reHDO240#s2P1IDyMIBscwwZ4ZPt z)WHrPpW#S4u$@Bxj}yHIHu-b9SanYtj!A`pntKt^uL0})1YNudq{-X9Bc%snJv}bp zPmXn-R^Y95*Nz$4%8oPO#Xhw1AipzO|Le>3IZYX3(wyd${d*HHiRxybK~ z|D~di?MAMSuj=YI^8a}zZ!2yWmGEb_1fEJ8 z{u?w!8G2mYHIFVgkHsm^1^*zFP805(vcwc;5&JUH6<%=za&rrdcE@9em}^N7RY`X1 z{~+ohD^__s-8b4!mJxS(lb09Q)gq4Hp?gilSvD%U&N=_UMIAdLUOGs~D^!x&Fq+Jf zOmb5+gz!UxV~~_p6!~!p><>(?hxGxPBAtykoM^H=t@%#i;sUR)>k6AuY{b{E)x86Y zuXX%>bUKAVWPXcEzZBBO$O5kMl-YCWJ&iZB_PPmsfp6@=OWvG*|8>$Vdt|gEt|0bh zCkzqIoh_#_{K?CxYr1OtSL^@aw!iG?7$?n`bJ6p}_5^w1R-0a8NzqXrQC~(a`0n%M>?w{vxr7cUZr2%C z&Uo>*~>lpv_R2M4qbFo;5x7HlxPBtjgy* zn4-9E)Rs^dJiLaG4wEFR<-uXLIAh?olr^4*_W_7=>=J!_pwRuyUsKcnV(qm(!(UI& zS^AQ2XAOFj%y?^f`7t@OJOVhrx3%r7I=Uh#*=M5eY;f Date: Thu, 25 Jun 2026 13:02:06 -0700 Subject: [PATCH 02/40] Add Todo App update --- aspnetcore/tutorials/min-web-api.md | 8 +- .../min-web-api/samples/10.x/todo/Program.cs | 110 ++++++++---------- .../min-web-api/samples/10.x/todo/Todo.cs | 2 +- .../samples/10.x/todo/TodoApi.csproj | 9 +- .../samples/10.x/todo/TodoApi.http | 6 + .../min-web-api/samples/10.x/todo/TodoDb.cs | 2 +- .../samples/10.x/todo/TodoPatchDto.cs | 2 +- .../10.x/todo/appsettings.Development.json | 8 ++ .../samples/10.x/todo/appsettings.json | 9 ++ 9 files changed, 83 insertions(+), 73 deletions(-) create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.http create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.Development.json create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.json diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index b3a737fcd97f..dea2c4fa8d45 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -58,7 +58,7 @@ This tutorial creates the following API: * In the **Additional information** dialog: * Confirm the **Framework** is **.NET 10.0 (Long Term Support)**. * Confirm the checkbox for **Enable OpenAPI support** is checked. - * **Uncheck** the checkbox for **Use controllers**. This checkbox is checked by default starting with Visual Studio 2026; uncheck it to create a Minimal API project instead of a controller-based one. + * Confirm the checkbox for **Use controllers** is **not** checked. Unchecking this setting creates a Minimal API project as required for this tutorial rather than a controller-based one. * Select **Create**. ![Additional information](~/tutorials/min-web-api/static/10/add-information-dialog-18-7-1.png) @@ -86,7 +86,7 @@ This tutorial creates the following API: The `Program.cs` file generated by the template contains the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_templatestart"::: The preceding code: @@ -142,13 +142,13 @@ The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program * In `Program.cs`, replace the `WeatherForecast` sample endpoint and the `WeatherForecast` record with the following code: -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_all)] + :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_minimal_start_all"::: The OpenAPI lines added by the template (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) remain in place. They now describe the Todo endpoints instead of the sample weather endpoint. The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container and enables displaying database-related exceptions: -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_DI&highlight=2-3)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_DI&highlight=2)] The DI container provides access to the database context and other services. diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs index 0cd1540ced1f..58695ba673f8 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs @@ -1,21 +1,58 @@ -#define FINAL // MINIMAL FINAL WITHPATCH TYPEDR -#if MINIMAL -// +#define WITHPATCH // TEMPLATESTART MINIMALSTART FINAL WITHPATCH TYPEDR +#if TEMPLATESTART +// var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi +builder.Services.AddOpenApi(); + var app = builder.Build(); -app.MapGet("/", () => "Hello World!"); +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +app.UseHttpsRedirection(); + +var summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/weatherforecast", () => +{ + var forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; +}) +.WithName("GetWeatherForecast"); app.Run(); -// + +internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} +// + #elif FINAL -// + +#elif MINIMALSTART +// using Microsoft.EntityFrameworkCore; // var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); var app = builder.Build(); // @@ -76,13 +113,13 @@ is Todo todo // app.Run(); -// + +// #elif WITHPATCH using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); var app = builder.Build(); app.MapGet("/todoitems", async (TodoDb db) => @@ -148,58 +185,7 @@ is Todo todo }); app.Run(); -#elif TYPEDR -using Microsoft.AspNetCore.Http.HttpResults; -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); -var app = builder.Build(); - -app.MapGet("/todoitems", async (TodoDb db) => - await db.Todos.ToListAsync()); - -app.MapGet("/todoitems/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -// -app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); -// -/* -// - app.MapGet("/todoitems/{id}", async Task, NotFound>> (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(todo) - : TypedResults.NotFound()); -// -*/ - -/* -// -app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(todo) - : TypedResults.NotFound()); -// -*/ - -// -app.MapGet("/hello", () => Results.Ok(new Message() { Text = "Hello World!" })) - .Produces(); -// - -// -app.MapGet("/hello2", () => TypedResults.Ok(new Message() { Text = "Hello World!" })); -// - -app.Run(); -#endif +#elif TYPEDR +#endif \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs index 2900a835b043..1c4cee9654dd 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs @@ -1,4 +1,4 @@ -class Todo +public class Todo { public int Id { get; set; } public string? Name { get; set; } diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj index abc9f7648bf9..0f463c5c9ea5 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj @@ -1,14 +1,15 @@ - + - net9.0 + net10.0 enable enable - - + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.http b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.http new file mode 100644 index 000000000000..eadf989b9134 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.http @@ -0,0 +1,6 @@ +@TodoApi_HostAddress = http://localhost:5290 + +GET {{TodoApi_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs index c1584b807819..b8229b1b6a25 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; class TodoDb : DbContext { diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs index ab225cf2280b..af8f27b8cf05 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs @@ -1,4 +1,4 @@ -public class TodoPatchDto +public class TodoPatchDto { public string? Name { get; set; } public bool? IsComplete { get; set; } diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.Development.json b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.Development.json new file mode 100644 index 000000000000..0c208ae9181e --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.json b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.json new file mode 100644 index 000000000000..10f68b8c8b4f --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From 867750dd6ec19163804a8d08a7a01915c07f4721 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Thu, 25 Jun 2026 20:47:42 -0700 Subject: [PATCH 03/40] Update aspnetcore/tutorials/min-web-api.md Co-authored-by: Mike Kistler --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index dea2c4fa8d45..ca7d38b3e9f8 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -371,7 +371,7 @@ Test the app by calling the `GET` endpoints from a browser or by using **Endpoin Test the app by calling the endpoints from a browser or Swagger. -* In Swagger select **GET /todoitems** > **Try it out** > **Execute**. +* In the Swagger UI select **GET /todoitems** > **Try it out** > **Execute**. * Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems`. For example, `http://localhost:7032/todoitems` From 955e38cf1712e0c59b03a5bef45a9fb8b73d6cda Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Fri, 26 Jun 2026 15:12:10 -0700 Subject: [PATCH 04/40] Update aspnetcore/tutorials/min-web-api.md Co-authored-by: Mike Kistler --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index ca7d38b3e9f8..eb8c80b89dcb 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -589,7 +589,7 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio Code](#tab/visual-studio-code) -Use Swagger to send a DELETE request: +Use the Swagger UI to send a DELETE request: * Select **DELETE /todoitems/{id}** > **Try it out**. * Set the **ID** field to `1` and select **Execute**. From 265a702d55e2db1b9121c3acd9ad7e41d44229c9 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Fri, 26 Jun 2026 15:30:31 -0700 Subject: [PATCH 05/40] Apply suggestions from code review Co-authored-by: Mike Kistler --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index eb8c80b89dcb..03cf32b9f40c 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -266,7 +266,7 @@ The POST endpoint will be used to add data to the app. # [Visual Studio Code](#tab/visual-studio-code) -* With the app still running, in the browser, navigate to `https://localhost:{port}/swagger` to display the API testing page generated by Swagger. +* With the app still running, in the browser, navigate to `https://localhost:{port}/swagger` to display the API testing page generated by NSwag. ![Swagger generated API testing page](~/tutorials/min-web-api/static/9.x/swagger.png) From e47562f1c66fdf4200a95b04137a24055bbbdc69 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Fri, 26 Jun 2026 15:31:18 -0700 Subject: [PATCH 06/40] Update aspnetcore/tutorials/min-web-api.md Co-authored-by: Mike Kistler --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 03cf32b9f40c..26b7ecca0e54 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -464,7 +464,7 @@ Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. # [Visual Studio Code](#tab/visual-studio-code) -Use Swagger to send a PUT request: +Use the Swagger UI to send a PUT request: * Select **Put /todoitems/{id}** > **Try it out**. From 6efa29f55f147da9bff951217933d21030acb165 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Fri, 26 Jun 2026 15:31:29 -0700 Subject: [PATCH 07/40] Update aspnetcore/tutorials/min-web-api.md Co-authored-by: Mike Kistler --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 26b7ecca0e54..1c6eecaa5180 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -543,7 +543,7 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n # [Visual Studio Code](#tab/visual-studio-code) -Use Swagger to send a PATCH request: +Use the Swagger UI to send a PATCH request: * Select **Patch /todoitems/{id}** > **Try it out**. From a5c780365efe61606f20af120b9e855cbfd7e216 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sat, 27 Jun 2026 19:54:01 -0700 Subject: [PATCH 08/40] Updated to use Scalar --- aspnetcore/tutorials/min-web-api.md | 279 ++++++++++++++++------------ 1 file changed, 160 insertions(+), 119 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 1c6eecaa5180..50b3f262da24 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -4,7 +4,7 @@ author: wadepickett description: Learn how to build a minimal API with ASP.NET Core. ai-usage: ai-assisted ms.author: wpickett -ms.date: 06/20/2026 +ms.date: 06/27/2026 monikerRange: '>= aspnetcore-6.0' uid: tutorials/min-web-api --- @@ -69,11 +69,11 @@ This tutorial creates the following API: * Change directories (`cd`) to the folder that will contain the project folder. * Run the following commands: - ```dotnetcli +```dotnetcli dotnet new webapi -o TodoApi cd TodoApi code -r ../TodoApi - ``` +``` * When a dialog box asks if you want to trust the authors, select **Yes**. * When a dialog box asks if you want to add required assets to the project, select **Yes**. @@ -86,8 +86,16 @@ This tutorial creates the following API: The `Program.cs` file generated by the template contains the following code: +# [Visual Studio](#tab/visual-studio) + :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_templatestart"::: +# [Visual Studio Code](#tab/visual-studio-code) + +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_templatestart"::: + +--- + The preceding code: * Creates a and a with preconfigured defaults. @@ -113,10 +121,10 @@ NuGet packages must be added to support the database and diagnostics used in thi * Run the following commands: - ```dotnetcli +```dotnetcli dotnet add package Microsoft.EntityFrameworkCore.InMemory dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore - ``` +``` --- @@ -126,10 +134,12 @@ NuGet packages must be added to support the database and diagnostics used in thi * In the project folder, create a file named `Todo.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Todo.cs"::: The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. +The `Secret` property isn't used by the API's endpoints yet. It represents a common real-world need: data the app stores and uses internally, such as the ID of the user who owns the item, that you don't want clients to see or set. In the [Prevent over-posting](#prevent-over-posting) step later in this tutorial, you'll use a Data Transfer Object (DTO) to keep fields like `Secret` out of the API's input and responses. + * Create a file named `TodoDb.cs` with the following code: :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs"::: @@ -142,55 +152,60 @@ The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program * In `Program.cs`, replace the `WeatherForecast` sample endpoint and the `WeatherForecast` record with the following code: - :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_minimal_start_all"::: +# [Visual Studio](#tab/visual-studio) -The OpenAPI lines added by the template (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) remain in place. They now describe the Todo endpoints instead of the sample weather endpoint. +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_minimal_start_all"::: -The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container and enables displaying database-related exceptions: +# [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_DI&highlight=2)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_minimal_start_all"::: -The DI container provides access to the database context and other services. +--- + +The OpenAPI lines added by the template (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) remain in place. They now describe the Todo endpoints instead of the sample weather endpoint. + +The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container and enables displaying database-related exceptions: # [Visual Studio](#tab/visual-studio) -This tutorial uses [Endpoints Explorer and .http files](xref:test/http-files#use-endpoints-explorer) to test the API. +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_DI&highlight=2-3)] # [Visual Studio Code](#tab/visual-studio-code) -### Add a browser UI to view the OpenAPI document +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_DI&highlight=2-3)] -The template already generates the OpenAPI document at `/openapi/v1.json`. To explore and test the API from a browser, add a UI that consumes that document. This tutorial uses NSwag. +--- -* Run the following command: +The DI container provides access to the database context and other services. + +# [Visual Studio](#tab/visual-studio) - ```dotnetcli - dotnet add package NSwag.AspNetCore - ``` -For more information on using OpenAPI and NSwag with ASP.NET, see . +This tutorial uses [Endpoints Explorer and .http files](xref:test/http-files#use-endpoints-explorer) to test the API. + +# [Visual Studio Code](#tab/visual-studio-code) ### Add a browser UI to view the OpenAPI document -The template already generates the OpenAPI document at `/openapi/v1.json`. To explore and test the API from a browser, add a UI that consumes that document. This tutorial uses NSwag. +The template already generates the OpenAPI document at `/openapi/v1.json`. To explore and test the API from a browser, add a UI that consumes that document. This tutorial uses Scalar. -Add the [NSwag.AspNetCore](https://www.nuget.org/packages/NSwag.AspNetCore/) package, which provides the middleware that serves the UI: +Add the [Scalar.AspNetCore](https://www.nuget.org/packages/Scalar.AspNetCore/) package, which provides the middleware that serves the UI: * Run the following command: - ```dotnetcli - dotnet add package NSwag.AspNetCore - ``` +```dotnetcli + dotnet add package Scalar.AspNetCore +``` -In this tutorial, NSwag is used only for its Swagger UI middleware, which reads the OpenAPI document already generated by OpenAPI. +In this tutorial, Scalar is used only for its API reference middleware, which reads the OpenAPI document already generated by OpenAPI. -* In `Program.cs`, add the following highlighted code inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: +* In `Program.cs`, add the `using` directive and the highlighted `MapScalarApiReference` line inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: - [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_swagger_ui&highlight=3-9)] + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_scalar&highlight=4)] - The preceding code enables the NSwag UI in Development only and points it at `/openapi/v1.json`, the document produced by `MapOpenApi()`. The UI itself is served at `/swagger`. + The preceding code enables the Scalar UI in Development only. It reads `/openapi/v1.json`, the document produced by `MapOpenApi()`, and serves the API reference at `/scalar/v1`. Be sure to add `using Scalar.AspNetCore;` to the top of the file. > [!NOTE] - > NSwag is one of several options for an OpenAPI UI. Alternatives such as [Scalar](https://www.nuget.org/packages/Scalar.AspNetCore/) or `Swashbuckle.AspNetCore.SwaggerUi` consume the same OpenAPI document and can be substituted for NSwag without changing the rest of the tutorial. + > Scalar is one of several options for an OpenAPI UI. Alternatives such as `NSwag.AspNetCore` or `Swashbuckle.AspNetCore.SwaggerUi` consume the same OpenAPI document and can be substituted for Scalar without changing the rest of the tutorial. @@ -200,8 +215,16 @@ In this tutorial, NSwag is used only for its Swagger UI middleware, which reads The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` that adds data to the in-memory database: +# [Visual Studio](#tab/visual-studio) + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_post)] +# [Visual Studio Code](#tab/visual-studio-code) + +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_post)] + +--- + Run the app. The browser displays a 404 error because there's no longer a `/` endpoint. The POST endpoint will be used to add data to the app. @@ -217,13 +240,13 @@ The POST endpoint will be used to add data to the app. A new file is created in the project folder named `TodoApi.http`, with contents similar to the following example: - ```http +```http @TodoApi_HostAddress = https://localhost:7031 POST {{TodoApi_HostAddress}}/todoitems ### - ``` +``` * The first line creates a variable that is used for all of the endpoints. * The next line defines a POST request. @@ -231,18 +254,18 @@ The POST endpoint will be used to add data to the app. * The POST request needs headers and a body. To define those parts of the request, add the following lines immediately after the POST request line: - ``` +``` Content-Type: application/json { "name":"walk dog", "isComplete":true } - ``` +``` The preceding code adds a Content-Type header and a JSON request body. The TodoApi.http file should now look like the following example, but with your port number: - ```http +```http @TodoApi_HostAddress = https://localhost:7057 POST {{TodoApi_HostAddress}}/todoitems @@ -254,7 +277,7 @@ The POST endpoint will be used to add data to the app. } ### - ``` +``` * Select the **Send request** link that is above the `POST` request line. @@ -266,41 +289,27 @@ The POST endpoint will be used to add data to the app. # [Visual Studio Code](#tab/visual-studio-code) -* With the app still running, in the browser, navigate to `https://localhost:{port}/swagger` to display the API testing page generated by NSwag. +* With the app still running, in the browser, navigate to `https://localhost:{port}/scalar/v1` to display the API reference page generated by Scalar. - ![Swagger generated API testing page](~/tutorials/min-web-api/static/9.x/swagger.png) - -* On the Swagger API testing page, select **Post /todoitems** > **Try it out**. -* Note that the **Request body** field contains a generated example format reflecting the parameters for the API. +* On the Scalar page, select the **POST /todoitems** operation, then select **Test Request**. * In the request body enter JSON for a to-do item, without specifying the optional `id`: - ```json +```json { "name":"walk dog", "isComplete":true } - ``` - -* Select **Execute**. - - ![Swagger with Post request](~/tutorials/min-web-api/static/9.x/swagger-post-1.png) - -Swagger provides a **Responses** pane below the **Execute** button. - - ![Swagger with Post response](~/tutorials/min-web-api/static/9.x/swagger-post-responses.png) +``` -Note a few of the useful details: +* Select **Send**. -* cURL: Swagger provides an example cURL command in Unix/Linux syntax, which can be run at the command line with any bash shell that uses Unix/Linux syntax, including Git Bash from [Git for Windows](https://git-scm.com/downloads). -* Request URL: A simplified representation of the HTTP request made by Swagger UI's JavaScript code for the API call. Actual requests can include details such as headers and query parameters and a request body. -* Server response: Includes the response body and headers. The response body shows the `id` was set to `1`. -* Response Code: A 201 `HTTP` status code was returned, indicating that the request was successfully processed and resulted in the creation of a new resource. +The Scalar UI displays the response, including the status code and response body. The response body shows the `id` was set to `1`. A 201 `HTTP` status code is returned, indicating that the request was successfully processed and resulted in the creation of a new resource. --- ## Examine the GET endpoints -Your `Program.cs` includes a single PUT endpoint, defined with `MapPut`: +Your `Program.cs` includes several GET endpoints, defined with `MapGet`: |API | Description | Request body | Response body | |--- | ---- | ---- | ---- | @@ -308,8 +317,16 @@ Your `Program.cs` includes a single PUT endpoint, defined with `MapPut`: |`GET /todoitems/complete` | Get all completed to-do items | None | Array of to-do items| |`GET /todoitems/{id}` | Get an item by ID | None | To-do item| +# [Visual Studio](#tab/visual-studio) + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_get)] +# [Visual Studio Code](#tab/visual-studio-code) + +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_get)] + +--- + ## Test the GET endpoints # [Visual Studio](#tab/visual-studio) @@ -320,11 +337,11 @@ Test the app by calling the `GET` endpoints from a browser or by using **Endpoin The following content is added to the `TodoApi.http` file: - ```http +```http GET {{TodoApi_HostAddress}}/todoitems ### - ``` +``` * Select the **Send request** link that is above the new `GET` request line. @@ -332,24 +349,25 @@ Test the app by calling the `GET` endpoints from a browser or by using **Endpoin * The response body is similar to the following JSON: - ```json +```json [ { "id": 1, "name": "walk dog", - "isComplete": true + "isComplete": true, + "secret": null } ] - ``` +``` * In **Endpoints Explorer**, right-click the `/todoitems/{id}` **GET** endpoint and select **Generate request**. The following content is added to the `TodoApi.http` file: - ```http +```http GET {{TodoApi_HostAddress}}/todoitems/{id} ### - ``` +``` * Replace `{id}` with `1`. @@ -359,19 +377,20 @@ Test the app by calling the `GET` endpoints from a browser or by using **Endpoin * The response body is similar to the following JSON: - ```json +```json { "id": 1, "name": "walk dog", - "isComplete": true + "isComplete": true, + "secret": null } - ``` +``` # [Visual Studio Code](#tab/visual-studio-code) -Test the app by calling the endpoints from a browser or Swagger. +Test the app by calling the endpoints from a browser or the Scalar UI. -* In the Swagger UI select **GET /todoitems** > **Try it out** > **Execute**. +* In the Scalar UI, select **GET /todoitems**, then **Test Request** > **Send**. * Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems`. For example, `http://localhost:7032/todoitems` @@ -382,26 +401,28 @@ The call to `GET /todoitems` produces a response similar to the following: { "id": 1, "name": "walk dog", - "isComplete": true + "isComplete": true, + "secret": null } ] ``` -* Call **GET /todoitems/{id}** in Swagger to return data from a specific id: - * Select **GET /todoitems** > **Try it out**. - * Set the **id** field to `1` and select **Execute**. +* Call **GET /todoitems/{id}** in Scalar to return data from a specific id: + * Select **GET /todoitems/{id}**, then **Test Request**. + * Set the **id** field to `1` and select **Send**. * Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems/1`. For example, `http://localhost:7032/todoitems/1` * The response is similar to the following: - ```json +```json { "id": 1, "name": "walk dog", - "isComplete": true + "isComplete": true, + "secret": null } - ``` +``` --- @@ -420,8 +441,16 @@ The return types can represent a wide range of HTTP status codes. For example, ` The sample app implements a single PUT endpoint using `MapPut`: +# [Visual Studio](#tab/visual-studio) + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_put)] +# [Visual Studio Code](#tab/visual-studio-code) + +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_put)] + +--- + This method is similar to the `MapPost` method, except it uses HTTP PUT. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use [HTTP PATCH](xref:Microsoft.AspNetCore.Mvc.HttpPatchAttribute). ## Test the PUT endpoint @@ -436,17 +465,17 @@ Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. The following content is added to the `TodoApi.http` file: - ```http +```http PUT {{TodoApi_HostAddress}}/todoitems/{id} ### - ``` +``` * In the PUT request line, replace `{id}` with `1`. * Add the following lines immediately after the PUT request line: - ```http +```http Content-Type: application/json { @@ -454,7 +483,7 @@ Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. "name": "feed fish", "isComplete": false } - ``` +``` The preceding code adds a Content-Type header and a JSON request body. @@ -464,23 +493,23 @@ Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. # [Visual Studio Code](#tab/visual-studio-code) -Use the Swagger UI to send a PUT request: +Use the Scalar UI to send a PUT request: -* Select **Put /todoitems/{id}** > **Try it out**. +* Select **PUT /todoitems/{id}**, then **Test Request**. * Set the **id** field to `1`. * Set the request body to the following JSON: - ```json +```json { "id": 1, "name": "feed fish", "isComplete": false } - ``` +``` -* Select **Execute**. +* Select **Send**. --- @@ -496,10 +525,18 @@ Create a file named `TodoPatchDto.cs` with the following code: The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to distinguish between a field that wasn't provided in the request versus a field explicitly set to a value. -The sample app implements a single PATCH endpoint using `MapPatch`: +* In `Program.cs`, add the following PATCH endpoint immediately after the `MapPut` endpoint: + +# [Visual Studio](#tab/visual-studio) [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_patch)] +# [Visual Studio Code](#tab/visual-studio-code) + +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_patch)] + +--- + This method is similar to the `MapPut` method, except it uses HTTP PATCH and only updates the fields provided in the request. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). > [!NOTE] @@ -517,23 +554,23 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n The following content is added to the `TodoApi.http` file: - ```http +```http PATCH {{TodoApi_HostAddress}}/todoitems/{id} ### - ``` +``` * In the PATCH request line, replace `{id}` with `1`. * Add the following lines immediately after the PATCH request line: - ```http +```http Content-Type: application/json { "name": "run errands" } - ``` +``` The preceding code adds a Content-Type header and a JSON request body with only the field to update. @@ -543,21 +580,21 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n # [Visual Studio Code](#tab/visual-studio-code) -Use the Swagger UI to send a PATCH request: +Use the Scalar UI to send a PATCH request: -* Select **Patch /todoitems/{id}** > **Try it out**. +* Select **PATCH /todoitems/{id}**, then **Test Request**. * Set the **id** field to `1`. * Set the request body to the following JSON: - ```json +```json { "name": "run errands" } - ``` +``` -* Select **Execute**. +* Select **Send**. --- @@ -565,8 +602,16 @@ Use the Swagger UI to send a PATCH request: Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: +# [Visual Studio](#tab/visual-studio) + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_delete)] +# [Visual Studio Code](#tab/visual-studio-code) + +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_delete)] + +--- + ## Test the DELETE endpoint # [Visual Studio](#tab/visual-studio) @@ -577,11 +622,11 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: * Replace `{id}` in the DELETE request line with `1`. The DELETE request should look like the following example: - ```http +```http DELETE {{TodoApi_HostAddress}}/todoitems/1 ### - ``` +``` * Select the **Send request** link for the DELETE request. @@ -589,12 +634,12 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio Code](#tab/visual-studio-code) -Use the Swagger UI to send a DELETE request: +Use the Scalar UI to send a DELETE request: -* Select **DELETE /todoitems/{id}** > **Try it out**. -* Set the **ID** field to `1` and select **Execute**. +* Select **DELETE /todoitems/{id}**, then **Test Request**. +* Set the **id** field to `1` and select **Send**. - The DELETE request is sent to the app and the response is displayed in the **Responses** pane. The response body is empty, and the **Server response** status code is 204. + The DELETE request is sent to the app and the response is displayed. The response body is empty, and the status code is 204. --- @@ -606,11 +651,11 @@ Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_mapgroup_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs" id="snippet_mapgroup_all"::: --- @@ -630,25 +675,25 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs" id="snippet_typed_all"::: --- The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_group"::: These methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs" id="snippet_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -670,7 +715,7 @@ public async Task GetAllTodos_ReturnsOkOfTodosResult() ## Prevent over-posting -Currently your API exposes the entire `Todo` object. In production applications, a subset of the model is often used to restrict the data that can be input and returned. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. **DTO** is used in this article. +Currently your API exposes the entire `Todo` object, including the `Secret` property you added in [The model and database context classes](#model-db-classes). In production applications, a subset of the model is often used to restrict the data that can be input and returned. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. **DTO** is used in this article. A DTO can be used to: @@ -679,31 +724,27 @@ A DTO can be used to: * Omit some properties to reduce payload size. * Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients. -To demonstrate the DTO approach, update the `Todo` class to include a secret field: - -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs"::: - -The secret field needs to be hidden from this app, but an administrative app could choose to expose it. +The `Secret` field needs to be hidden from this app, but an administrative app could choose to expose it. -Verify you can post and get the secret field. +Verify you can post and get the `Secret` field with the current endpoints. Create a file named `TodoItemDTO.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoItemDTO.cs"::: Replace the contents of the `Program.cs` file with the following code to use this DTO model: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_dto_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs" id="snippet_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs" id="snippet_dto_all"::: --- -Verify you can post and get all fields except the secret field. +Verify you can post and get all fields except the `Secret` field. @@ -728,4 +769,4 @@ See [!INCLUDE[](~/tutorials/min-web-api/includes/min-web-api-6-7.md)] [!INCLUDE[](~/tutorials/min-web-api/includes/min-web-api-8.md)] -[!INCLUDE[](~/tutorials/min-web-api/includes/min-web-api-9.md)] +[!INCLUDE[](~/tutorials/min-web-api/includes/min-web-api-9.md)] \ No newline at end of file From 9ff025e9b0cc599de4b44796e922b0802161bbe6 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sat, 27 Jun 2026 20:03:12 -0700 Subject: [PATCH 09/40] Addressed review suggestions. --- aspnetcore/tutorials/min-web-api.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 50b3f262da24..8424701f073c 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -146,6 +146,8 @@ The `Secret` property isn't used by the API's endpoints yet. It represents a com The preceding code defines the *database context*, which is the main class that coordinates [Entity Framework](/ef/core/) functionality for a data model. This class derives from the class. +The app uses an in-memory database named `TodoList`. The database is registered later in `Program.cs` with `builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList"));`, where the string `"TodoList"` is the database name. Because the data is stored in memory, it's reset every time the app restarts. + ## Replace the WeatherForecast sample with the Todo API The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program.cs` and a `WeatherForecast` record at the bottom of the file. The sample is just a placeholder to show the template works — replace both with the Todo endpoints below. @@ -426,7 +428,7 @@ The call to `GET /todoitems` produces a response similar to the following: --- -This app uses an in-memory database. If the app is restarted, the GET request doesn't return any data. If no data is returned, [POST](#post) data to the app and try the GET request again. +This app uses an in-memory database. If the app is restarted, the data is lost: `GET /todoitems` returns an empty array (`[]`), and `GET /todoitems/{id}` returns a `404 Not Found`. To repopulate the app, [POST](#post) data to the app and try the GET request again. ## Return values From 0c6e4680fe9b98e2627554dc49f4c43d0e4308cc Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sat, 27 Jun 2026 20:18:41 -0700 Subject: [PATCH 10/40] Updating to new app samples now only one for VS and one for Scalar - VS code. --- .../Program-default-before-replacing.cs | 41 -- .../min-web-api/samples/10.x/todo/Message.cs | 8 - .../min-web-api/samples/10.x/todo/Program.cs | 191 ------- .../min-web-api/samples/10.x/todo/Todo.cs | 6 - .../samples/10.x/todo/TodoApi/Program.cs | 459 ++++++++++++++++ .../10.x/{todoDTO => todo/TodoApi}/Todo.cs | 2 +- .../10.x/todo/{ => TodoApi}/TodoApi.csproj | 0 .../10.x/todo/{ => TodoApi}/TodoApi.http | 0 .../samples/10.x/todo/{ => TodoApi}/TodoDb.cs | 0 .../TodoApi}/TodoItemDTO.cs | 4 +- .../10.x/todo/{ => TodoApi}/TodoPatchDto.cs | 0 .../appsettings.Development.json | 0 .../10.x/todo/{ => TodoApi}/appsettings.json | 0 .../samples/10.x/todoDTO/Program.cs | 84 --- .../samples/10.x/todoDTO/TodoApi.csproj | 14 - .../samples/10.x/todoDTO/TodoDb.cs | 9 - .../10.x/todoDTO_SwaggerVersion/Program.cs | 105 ---- .../todoDTO_SwaggerVersion/TodoApi.csproj | 15 - .../samples/10.x/todoGroup/Program.cs | 60 --- .../samples/10.x/todoGroup/Todo.cs | 6 - .../samples/10.x/todoGroup/TodoApi.csproj | 14 - .../samples/10.x/todoGroup/TodoDb.cs | 9 - .../10.x/todoGroup_SwaggerVersion/Program.cs | 81 --- .../10.x/todoGroup_SwaggerVersion/Todo.cs | 6 - .../10.x/todoGroup_SwaggerVersion/TodoDb.cs | 9 - .../samples/10.x/todoTypedResults/Program.cs | 79 --- .../samples/10.x/todoTypedResults/Todo.cs | 6 - .../10.x/todoTypedResults/TodoApi.csproj | 14 - .../samples/10.x/todoTypedResults/TodoDb.cs | 9 - .../Program.cs | 100 ---- .../todoTypedResults_SwaggerVersion/Todo.cs | 6 - .../TodoApi.csproj | 15 - .../todoTypedResults_SwaggerVersion/TodoDb.cs | 9 - .../todo_ScalarVersion/TodoApi/Program.cs | 494 ++++++++++++++++++ .../TodoApi}/Todo.cs | 2 +- .../TodoApi}/TodoApi.csproj | 8 +- .../TodoApi}/TodoDb.cs | 2 +- .../TodoApi}/TodoItemDTO.cs | 4 +- .../TodoApi/TodoPatchDto.cs | 5 + .../TodoApi/appsettings.Development.json | 8 + .../TodoApi/appsettings.json | 9 + .../10.x/todo_SwaggerVersion/Program.cs | 149 ------ .../samples/10.x/todo_SwaggerVersion/Todo.cs | 6 - .../10.x/todo_SwaggerVersion/TodoApi.csproj | 15 - .../10.x/todo_SwaggerVersion/TodoDb.cs | 9 - 45 files changed, 986 insertions(+), 1086 deletions(-) delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Program.cs rename aspnetcore/tutorials/min-web-api/samples/10.x/{todoDTO => todo/TodoApi}/Todo.cs (88%) rename aspnetcore/tutorials/min-web-api/samples/10.x/todo/{ => TodoApi}/TodoApi.csproj (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/todo/{ => TodoApi}/TodoApi.http (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/todo/{ => TodoApi}/TodoDb.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todoDTO_SwaggerVersion => todo/TodoApi}/TodoItemDTO.cs (90%) rename aspnetcore/tutorials/min-web-api/samples/10.x/todo/{ => TodoApi}/TodoPatchDto.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/todo/{ => TodoApi}/appsettings.Development.json (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/todo/{ => TodoApi}/appsettings.json (100%) delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Program.cs rename aspnetcore/tutorials/min-web-api/samples/10.x/{todoDTO_SwaggerVersion => todo_ScalarVersion/TodoApi}/Todo.cs (88%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todoGroup_SwaggerVersion => todo_ScalarVersion/TodoApi}/TodoApi.csproj (62%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todoDTO_SwaggerVersion => todo_ScalarVersion/TodoApi}/TodoDb.cs (79%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todoDTO => todo_ScalarVersion/TodoApi}/TodoItemDTO.cs (90%) create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoPatchDto.cs create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.Development.json create mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.json delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj delete mode 100644 aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs deleted file mode 100644 index ad8699de7b6b..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/SnippetsTutorialReferenceOnly/Program-default-before-replacing.cs +++ /dev/null @@ -1,41 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. -// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi -builder.Services.AddOpenApi(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.MapOpenApi(); -} - -app.UseHttpsRedirection(); - -var summaries = new[] -{ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" -}; - -app.MapGet("/weatherforecast", () => -{ - var forecast = Enumerable.Range(1, 5).Select(index => - new WeatherForecast - ( - DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - Random.Shared.Next(-20, 55), - summaries[Random.Shared.Next(summaries.Length)] - )) - .ToArray(); - return forecast; -}) -.WithName("GetWeatherForecast"); - -app.Run(); - -internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) -{ - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs deleted file mode 100644 index b352fffdee18..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Message.cs +++ /dev/null @@ -1,8 +0,0 @@ -public class Message -{ - public Message() - { - } - - public string Text { get; set; } -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs deleted file mode 100644 index 58695ba673f8..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Program.cs +++ /dev/null @@ -1,191 +0,0 @@ -#define WITHPATCH // TEMPLATESTART MINIMALSTART FINAL WITHPATCH TYPEDR -#if TEMPLATESTART -// -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. -// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi -builder.Services.AddOpenApi(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.MapOpenApi(); -} - -app.UseHttpsRedirection(); - -var summaries = new[] -{ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" -}; - -app.MapGet("/weatherforecast", () => -{ - var forecast = Enumerable.Range(1, 5).Select(index => - new WeatherForecast - ( - DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - Random.Shared.Next(-20, 55), - summaries[Random.Shared.Next(summaries.Length)] - )) - .ToArray(); - return forecast; -}) -.WithName("GetWeatherForecast"); - -app.Run(); - -internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) -{ - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} -// - -#elif FINAL - -#elif MINIMALSTART -// -using Microsoft.EntityFrameworkCore; - -// -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -var app = builder.Build(); -// - -// -app.MapGet("/todoitems", async (TodoDb db) => - await db.Todos.ToListAsync()); - -app.MapGet("/todoitems/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -// -app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); -// -// - -// -app.MapPost("/todoitems", async (Todo todo, TodoDb db) => -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return Results.Created($"/todoitems/{todo.Id}", todo); -}); -// - -// -app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return Results.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); -// - -// -app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return Results.NoContent(); - } - - return Results.NotFound(); -}); -// - -app.Run(); - -// -#elif WITHPATCH -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -var app = builder.Build(); - -app.MapGet("/todoitems", async (TodoDb db) => - await db.Todos.ToListAsync()); - -app.MapGet("/todoitems/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); - -app.MapPost("/todoitems", async (Todo todo, TodoDb db) => -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return Results.Created($"/todoitems/{todo.Id}", todo); -}); - -app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return Results.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); - -// -app.MapPatch("/todoitems/{id}", async (int id, TodoPatchDto inputTodo, TodoDb db) => -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return Results.NotFound(); - - if (inputTodo.Name is not null) todo.Name = inputTodo.Name; - if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; - - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); -// - -app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return Results.NoContent(); - } - - return Results.NotFound(); -}); - -app.Run(); - -#elif TYPEDR - -#endif \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs deleted file mode 100644 index 1c4cee9654dd..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/Todo.cs +++ /dev/null @@ -1,6 +0,0 @@ -public class Todo -{ - public int Id { get; set; } - public string? Name { get; set; } - public bool IsComplete { get; set; } -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Program.cs new file mode 100644 index 000000000000..c54e47801d51 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Program.cs @@ -0,0 +1,459 @@ +#define PREVENTOVERPOST // TEMPLATESTART MINIMALSTART WITHPATCH MAPGROUP TYPED PREVENTOVERPOST +#if TEMPLATESTART +// +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi +builder.Services.AddOpenApi(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +app.UseHttpsRedirection(); + +var summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/weatherforecast", () => +{ + var forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; +}) +.WithName("GetWeatherForecast"); + +app.Run(); + +internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} +// + +#elif MINIMALSTART +// +using Microsoft.EntityFrameworkCore; + +// +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +var app = builder.Build(); +// + +// +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +// +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); +// +// + +// +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); +// + +// +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +// +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); +// + +app.Run(); + +// +#elif WITHPATCH +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +// +app.MapPatch("/todoitems/{id}", async (int id, TodoPatchDto inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); + +app.Run(); + +#elif MAPGROUP +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", async (TodoDb db) => + await db.Todos.ToListAsync()); + +todoItems.MapGet("/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +todoItems.MapGet("/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +todoItems.MapPost("/", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +todoItems.MapPatch("/{id}", async (int id, TodoPatchDto inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +todoItems.MapDelete("/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); + +app.Run(); + +#elif TYPED +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapPatch("/{id}", PatchTodo); +todoItems.MapDelete("/{id}", DeleteTodo); + +app.Run(); + +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.ToArrayAsync()); +} + +static async Task GetCompleteTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync()); +} + +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound(); +} + +static async Task CreateTodo(Todo todo, TodoDb db) +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return TypedResults.Created($"/todoitems/{todo.Id}", todo); +} + +static async Task UpdateTodo(int id, Todo inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task PatchTodo(int id, TodoPatchDto inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} + +#elif PREVENTOVERPOST +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapPatch("/{id}", PatchTodo); +todoItems.MapDelete("/{id}", DeleteTodo); + +app.Run(); + +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync()); +} + +static async Task GetCompleteTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync()); +} + +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(new TodoItemDTO(todo)) + : TypedResults.NotFound(); +} + +static async Task CreateTodo(TodoItemDTO todoItemDTO, TodoDb db) +{ + var todoItem = new Todo + { + IsComplete = todoItemDTO.IsComplete, + Name = todoItemDTO.Name + }; + + db.Todos.Add(todoItem); + await db.SaveChangesAsync(); + + todoItemDTO = new TodoItemDTO(todoItem); + + return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO); +} + +static async Task UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = todoItemDTO.Name; + todo.IsComplete = todoItemDTO.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task PatchTodo(int id, TodoPatchDto inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +#endif diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Todo.cs similarity index 88% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Todo.cs index d9ea203029c5..44593bed1e7c 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Todo.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Todo.cs @@ -1,4 +1,4 @@ -public class Todo +public class Todo { public int Id { get; set; } public string? Name { get; set; } diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.csproj similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.csproj rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.csproj diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.http b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.http similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi.http rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.http diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoDb.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoDb.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoItemDTO.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoItemDTO.cs similarity index 90% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoItemDTO.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoItemDTO.cs index 76f99abe44bd..68ecca65299c 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoItemDTO.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoItemDTO.cs @@ -1,4 +1,4 @@ -public class TodoItemDTO +public class TodoItemDTO { public int Id { get; set; } public string? Name { get; set; } @@ -7,4 +7,4 @@ public class TodoItemDTO public TodoItemDTO() { } public TodoItemDTO(Todo todoItem) => (Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete); -} +} \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoPatchDto.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoPatchDto.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.Development.json b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.Development.json similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.Development.json rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.Development.json diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.json b/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.json similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/appsettings.json rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.json diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs deleted file mode 100644 index 861c355b7387..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/Program.cs +++ /dev/null @@ -1,84 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); -var app = builder.Build(); - -// -RouteGroupBuilder todoItems = app.MapGroup("/todoitems"); - -todoItems.MapGet("/", GetAllTodos); -todoItems.MapGet("/complete", GetCompleteTodos); -todoItems.MapGet("/{id}", GetTodo); -todoItems.MapPost("/", CreateTodo); -todoItems.MapPut("/{id}", UpdateTodo); -todoItems.MapDelete("/{id}", DeleteTodo); -// - -app.Run(); - -// -// -static async Task GetAllTodos(TodoDb db) -{ - return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync()); -} -// - -static async Task GetCompleteTodos(TodoDb db) { - return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync()); -} - -static async Task GetTodo(int id, TodoDb db) -{ - return await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(new TodoItemDTO(todo)) - : TypedResults.NotFound(); -} - -static async Task CreateTodo(TodoItemDTO todoItemDTO, TodoDb db) -{ - var todoItem = new Todo - { - IsComplete = todoItemDTO.IsComplete, - Name = todoItemDTO.Name - }; - - db.Todos.Add(todoItem); - await db.SaveChangesAsync(); - - todoItemDTO = new TodoItemDTO(todoItem); - - return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO); -} - -static async Task UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db) -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return TypedResults.NotFound(); - - todo.Name = todoItemDTO.Name; - todo.IsComplete = todoItemDTO.IsComplete; - - await db.SaveChangesAsync(); - - return TypedResults.NoContent(); -} - -static async Task DeleteTodo(int id, TodoDb db) -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return TypedResults.NoContent(); - } - - return TypedResults.NotFound(); -} -// -// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj deleted file mode 100644 index abc9f7648bf9..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoApi.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs deleted file mode 100644 index c1584b807819..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoDb.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -class TodoDb : DbContext -{ - public TodoDb(DbContextOptions options) - : base(options) { } - - public DbSet Todos => Set(); -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs deleted file mode 100644 index aa53df894a24..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Program.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); - -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddOpenApiDocument(config => -{ - config.DocumentName = "TodoAPI"; - config.Title = "TodoAPI v1"; - config.Version = "v1"; -}); - -var app = builder.Build(); - -if (app.Environment.IsDevelopment()) -{ - app.UseOpenApi(); - app.UseSwaggerUi(config => - { - config.DocumentTitle = "TodoAPI"; - config.Path = "/swagger"; - config.DocumentPath = "/swagger/{documentName}/swagger.json"; - config.DocExpansion = "list"; - }); -} - -// -RouteGroupBuilder todoItems = app.MapGroup("/todoitems"); - -todoItems.MapGet("/", GetAllTodos); -todoItems.MapGet("/complete", GetCompleteTodos); -todoItems.MapGet("/{id}", GetTodo); -todoItems.MapPost("/", CreateTodo); -todoItems.MapPut("/{id}", UpdateTodo); -todoItems.MapDelete("/{id}", DeleteTodo); -// - -app.Run(); - -// -// -static async Task GetAllTodos(TodoDb db) -{ - return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync()); -} -// - -static async Task GetCompleteTodos(TodoDb db) { - return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync()); -} - -static async Task GetTodo(int id, TodoDb db) -{ - return await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(new TodoItemDTO(todo)) - : TypedResults.NotFound(); -} - -static async Task CreateTodo(TodoItemDTO todoItemDTO, TodoDb db) -{ - var todoItem = new Todo - { - IsComplete = todoItemDTO.IsComplete, - Name = todoItemDTO.Name - }; - - db.Todos.Add(todoItem); - await db.SaveChangesAsync(); - - todoItemDTO = new TodoItemDTO(todoItem); - - return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO); -} - -static async Task UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db) -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return TypedResults.NotFound(); - - todo.Name = todoItemDTO.Name; - todo.IsComplete = todoItemDTO.IsComplete; - - await db.SaveChangesAsync(); - - return TypedResults.NoContent(); -} - -static async Task DeleteTodo(int id, TodoDb db) -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return TypedResults.NoContent(); - } - - return TypedResults.NotFound(); -} -// -// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj deleted file mode 100644 index 067275c7128b..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoApi.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs deleted file mode 100644 index 2a82ad8c9f76..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Program.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); -var app = builder.Build(); - -// -var todoItems = app.MapGroup("/todoitems"); - -todoItems.MapGet("/", async (TodoDb db) => - await db.Todos.ToListAsync()); - -todoItems.MapGet("/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -todoItems.MapGet("/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); - -todoItems.MapPost("/", async (Todo todo, TodoDb db) => -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return Results.Created($"/todoitems/{todo.Id}", todo); -}); - -todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) => -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return Results.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); - -todoItems.MapDelete("/{id}", async (int id, TodoDb db) => -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return Results.NoContent(); - } - - return Results.NotFound(); -}); -// - -app.Run(); -// \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs deleted file mode 100644 index 986d0c7de8c4..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/Todo.cs +++ /dev/null @@ -1,6 +0,0 @@ -public class Todo -{ - public int Id { get; set; } - public string? Name { get; set; } - public bool IsComplete { get; set; } -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj deleted file mode 100644 index abc9f7648bf9..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoApi.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs deleted file mode 100644 index c1584b807819..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup/TodoDb.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -class TodoDb : DbContext -{ - public TodoDb(DbContextOptions options) - : base(options) { } - - public DbSet Todos => Set(); -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs deleted file mode 100644 index 3787cd75a0ce..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Program.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); - -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddOpenApiDocument(config => -{ - config.DocumentName = "TodoAPI"; - config.Title = "TodoAPI v1"; - config.Version = "v1"; -}); - -var app = builder.Build(); - -if (app.Environment.IsDevelopment()) -{ - app.UseOpenApi(); - app.UseSwaggerUi(config => - { - config.DocumentTitle = "TodoAPI"; - config.Path = "/swagger"; - config.DocumentPath = "/swagger/{documentName}/swagger.json"; - config.DocExpansion = "list"; - }); -} - -// -var todoItems = app.MapGroup("/todoitems"); - -todoItems.MapGet("/", async (TodoDb db) => - await db.Todos.ToListAsync()); - -todoItems.MapGet("/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -todoItems.MapGet("/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); - -todoItems.MapPost("/", async (Todo todo, TodoDb db) => -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return Results.Created($"/todoitems/{todo.Id}", todo); -}); - -todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) => -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return Results.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); - -todoItems.MapDelete("/{id}", async (int id, TodoDb db) => -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return Results.NoContent(); - } - - return Results.NotFound(); -}); -// - -app.Run(); -// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs deleted file mode 100644 index 986d0c7de8c4..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/Todo.cs +++ /dev/null @@ -1,6 +0,0 @@ -public class Todo -{ - public int Id { get; set; } - public string? Name { get; set; } - public bool IsComplete { get; set; } -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs deleted file mode 100644 index c1584b807819..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoDb.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -class TodoDb : DbContext -{ - public TodoDb(DbContextOptions options) - : base(options) { } - - public DbSet Todos => Set(); -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs deleted file mode 100644 index 591f97decb52..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Program.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); -var app = builder.Build(); - -// -var todoItems = app.MapGroup("/todoitems"); - -todoItems.MapGet("/", GetAllTodos); -todoItems.MapGet("/complete", GetCompleteTodos); -todoItems.MapGet("/{id}", GetTodo); -todoItems.MapPost("/", CreateTodo); -todoItems.MapPut("/{id}", UpdateTodo); -todoItems.MapDelete("/{id}", DeleteTodo); -// - -app.Run(); - -// -// -static async Task GetAllTodos(TodoDb db) -{ - return TypedResults.Ok(await db.Todos.ToArrayAsync()); -} -// - -static async Task GetCompleteTodos(TodoDb db) -{ - return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync()); -} - -// -static async Task GetTodo(int id, TodoDb db) -{ - return await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(todo) - : TypedResults.NotFound(); -} -// - -static async Task CreateTodo(Todo todo, TodoDb db) -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return TypedResults.Created($"/todoitems/{todo.Id}", todo); -} - -static async Task UpdateTodo(int id, Todo inputTodo, TodoDb db) -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return TypedResults.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return TypedResults.NoContent(); -} - -static async Task DeleteTodo(int id, TodoDb db) -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return TypedResults.NoContent(); - } - - return TypedResults.NotFound(); -} -// -// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs deleted file mode 100644 index 2900a835b043..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/Todo.cs +++ /dev/null @@ -1,6 +0,0 @@ -class Todo -{ - public int Id { get; set; } - public string? Name { get; set; } - public bool IsComplete { get; set; } -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj deleted file mode 100644 index abc9f7648bf9..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoApi.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs deleted file mode 100644 index c1584b807819..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults/TodoDb.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -class TodoDb : DbContext -{ - public TodoDb(DbContextOptions options) - : base(options) { } - - public DbSet Todos => Set(); -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs deleted file mode 100644 index 522968205c21..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Program.cs +++ /dev/null @@ -1,100 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); - -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddOpenApiDocument(config => -{ - config.DocumentName = "TodoAPI"; - config.Title = "TodoAPI v1"; - config.Version = "v1"; -}); - -var app = builder.Build(); - -if (app.Environment.IsDevelopment()) -{ - app.UseOpenApi(); - app.UseSwaggerUi(config => - { - config.DocumentTitle = "TodoAPI"; - config.Path = "/swagger"; - config.DocumentPath = "/swagger/{documentName}/swagger.json"; - config.DocExpansion = "list"; - }); -} - -// -var todoItems = app.MapGroup("/todoitems"); - -todoItems.MapGet("/", GetAllTodos); -todoItems.MapGet("/complete", GetCompleteTodos); -todoItems.MapGet("/{id}", GetTodo); -todoItems.MapPost("/", CreateTodo); -todoItems.MapPut("/{id}", UpdateTodo); -todoItems.MapDelete("/{id}", DeleteTodo); -// - -app.Run(); - -// -// -static async Task GetAllTodos(TodoDb db) -{ - return TypedResults.Ok(await db.Todos.ToArrayAsync()); -} -// - -static async Task GetCompleteTodos(TodoDb db) -{ - return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync()); -} - -// -static async Task GetTodo(int id, TodoDb db) -{ - return await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(todo) - : TypedResults.NotFound(); -} -// - -static async Task CreateTodo(Todo todo, TodoDb db) -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return TypedResults.Created($"/todoitems/{todo.Id}", todo); -} - -static async Task UpdateTodo(int id, Todo inputTodo, TodoDb db) -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return TypedResults.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return TypedResults.NoContent(); -} - -static async Task DeleteTodo(int id, TodoDb db) -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return TypedResults.NoContent(); - } - - return TypedResults.NotFound(); -} -// -// diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs deleted file mode 100644 index 2900a835b043..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/Todo.cs +++ /dev/null @@ -1,6 +0,0 @@ -class Todo -{ - public int Id { get; set; } - public string? Name { get; set; } - public bool IsComplete { get; set; } -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj deleted file mode 100644 index 067275c7128b..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoApi.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs deleted file mode 100644 index c1584b807819..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoTypedResults_SwaggerVersion/TodoDb.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -class TodoDb : DbContext -{ - public TodoDb(DbContextOptions options) - : base(options) { } - - public DbSet Todos => Set(); -} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Program.cs new file mode 100644 index 000000000000..12ea67824c2a --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Program.cs @@ -0,0 +1,494 @@ +#define PREVENTOVERPOST // TEMPLATESTART MINIMALSTART WITHPATCH MAPGROUP TYPED PREVENTOVERPOST +#if TEMPLATESTART +// +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi +builder.Services.AddOpenApi(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + +app.UseHttpsRedirection(); + +var summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/weatherforecast", () => +{ + var forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; +}) +.WithName("GetWeatherForecast"); + +app.Run(); + +internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} +// + +#elif MINIMALSTART +// +using Microsoft.EntityFrameworkCore; +using Scalar.AspNetCore; + +// +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +builder.Services.AddOpenApi(); +var app = builder.Build(); +// + +// +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.MapScalarApiReference(); +} +// + +// +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); +// + +// +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); +// + +// +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +// +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); +// + +app.Run(); +// + +#elif WITHPATCH +// +using Microsoft.EntityFrameworkCore; +using Scalar.AspNetCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.MapScalarApiReference(); +} + +app.MapGet("/todoitems", async (TodoDb db) => + await db.Todos.ToListAsync()); + +app.MapGet("/todoitems/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +app.MapPost("/todoitems", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +// +app.MapPatch("/todoitems/{id}", async (int id, TodoPatchDto inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); +// + +app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); + +app.Run(); +// + +#elif MAPGROUP +// +using Microsoft.EntityFrameworkCore; +using Scalar.AspNetCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.MapScalarApiReference(); +} + +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", async (TodoDb db) => + await db.Todos.ToListAsync()); + +todoItems.MapGet("/complete", async (TodoDb db) => + await db.Todos.Where(t => t.IsComplete).ToListAsync()); + +todoItems.MapGet("/{id}", async (int id, TodoDb db) => + await db.Todos.FindAsync(id) + is Todo todo + ? Results.Ok(todo) + : Results.NotFound()); + +todoItems.MapPost("/", async (Todo todo, TodoDb db) => +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return Results.Created($"/todoitems/{todo.Id}", todo); +}); + +todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +todoItems.MapPatch("/{id}", async (int id, TodoPatchDto inputTodo, TodoDb db) => +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return Results.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return Results.NoContent(); +}); + +todoItems.MapDelete("/{id}", async (int id, TodoDb db) => +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return Results.NoContent(); + } + + return Results.NotFound(); +}); + +app.Run(); +// + +#elif TYPED +// +using Microsoft.EntityFrameworkCore; +using Scalar.AspNetCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.MapScalarApiReference(); +} + +// +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapPatch("/{id}", PatchTodo); +todoItems.MapDelete("/{id}", DeleteTodo); +// + +app.Run(); + +// +// +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.ToArrayAsync()); +} +// + +static async Task GetCompleteTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync()); +} + +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(todo) + : TypedResults.NotFound(); +} + +static async Task CreateTodo(Todo todo, TodoDb db) +{ + db.Todos.Add(todo); + await db.SaveChangesAsync(); + + return TypedResults.Created($"/todoitems/{todo.Id}", todo); +} + +static async Task UpdateTodo(int id, Todo inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = inputTodo.Name; + todo.IsComplete = inputTodo.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task PatchTodo(int id, TodoPatchDto inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +// +// + +#elif PREVENTOVERPOST +// +using Microsoft.EntityFrameworkCore; +using Scalar.AspNetCore; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); +builder.Services.AddOpenApi(); +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.MapScalarApiReference(); +} + +var todoItems = app.MapGroup("/todoitems"); + +todoItems.MapGet("/", GetAllTodos); +todoItems.MapGet("/complete", GetCompleteTodos); +todoItems.MapGet("/{id}", GetTodo); +todoItems.MapPost("/", CreateTodo); +todoItems.MapPut("/{id}", UpdateTodo); +todoItems.MapPatch("/{id}", PatchTodo); +todoItems.MapDelete("/{id}", DeleteTodo); + +app.Run(); + +static async Task GetAllTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync()); +} + +static async Task GetCompleteTodos(TodoDb db) +{ + return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync()); +} + +static async Task GetTodo(int id, TodoDb db) +{ + return await db.Todos.FindAsync(id) + is Todo todo + ? TypedResults.Ok(new TodoItemDTO(todo)) + : TypedResults.NotFound(); +} + +static async Task CreateTodo(TodoItemDTO todoItemDTO, TodoDb db) +{ + var todoItem = new Todo + { + IsComplete = todoItemDTO.IsComplete, + Name = todoItemDTO.Name + }; + + db.Todos.Add(todoItem); + await db.SaveChangesAsync(); + + todoItemDTO = new TodoItemDTO(todoItem); + + return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO); +} + +static async Task UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + todo.Name = todoItemDTO.Name; + todo.IsComplete = todoItemDTO.IsComplete; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task PatchTodo(int id, TodoPatchDto inputTodo, TodoDb db) +{ + var todo = await db.Todos.FindAsync(id); + + if (todo is null) return TypedResults.NotFound(); + + if (inputTodo.Name is not null) todo.Name = inputTodo.Name; + if (inputTodo.IsComplete is not null) todo.IsComplete = inputTodo.IsComplete.Value; + + await db.SaveChangesAsync(); + + return TypedResults.NoContent(); +} + +static async Task DeleteTodo(int id, TodoDb db) +{ + if (await db.Todos.FindAsync(id) is Todo todo) + { + db.Todos.Remove(todo); + await db.SaveChangesAsync(); + return TypedResults.NoContent(); + } + + return TypedResults.NotFound(); +} +// +#endif \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Todo.cs similarity index 88% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Todo.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Todo.cs index d9ea203029c5..44593bed1e7c 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/Todo.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Todo.cs @@ -1,4 +1,4 @@ -public class Todo +public class Todo { public int Id { get; set; } public string? Name { get; set; } diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoApi.csproj similarity index 62% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoApi.csproj rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoApi.csproj index 067275c7128b..0f463c5c9ea5 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoGroup_SwaggerVersion/TodoApi.csproj +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoApi.csproj @@ -1,15 +1,15 @@ - net8.0 + net10.0 enable enable - - - + + + diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoDb.cs similarity index 79% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoDb.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoDb.cs index c1584b807819..b8229b1b6a25 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO_SwaggerVersion/TodoDb.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoDb.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; class TodoDb : DbContext { diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoItemDTO.cs similarity index 90% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoItemDTO.cs index 76f99abe44bd..68ecca65299c 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todoDTO/TodoItemDTO.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoItemDTO.cs @@ -1,4 +1,4 @@ -public class TodoItemDTO +public class TodoItemDTO { public int Id { get; set; } public string? Name { get; set; } @@ -7,4 +7,4 @@ public class TodoItemDTO public TodoItemDTO() { } public TodoItemDTO(Todo todoItem) => (Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete); -} +} \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoPatchDto.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoPatchDto.cs new file mode 100644 index 000000000000..af8f27b8cf05 --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoPatchDto.cs @@ -0,0 +1,5 @@ +public class TodoPatchDto +{ + public string? Name { get; set; } + public bool? IsComplete { get; set; } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.Development.json b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.Development.json new file mode 100644 index 000000000000..0c208ae9181e --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.json b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.json new file mode 100644 index 000000000000..10f68b8c8b4f --- /dev/null +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs deleted file mode 100644 index b657be5cd7ad..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Program.cs +++ /dev/null @@ -1,149 +0,0 @@ -#define FINAL // MINIMAL FINAL TYPEDR -#if MINIMAL -// -var builder = WebApplication.CreateBuilder(args); -var app = builder.Build(); - -app.MapGet("/", () => "Hello World!"); - -app.Run(); -// -#elif FINAL -// -// -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); - -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddOpenApiDocument(config => -{ - config.DocumentName = "TodoAPI"; - config.Title = "TodoAPI v1"; - config.Version = "v1"; -}); -// -var app = builder.Build(); -// -if (app.Environment.IsDevelopment()) -{ - app.UseOpenApi(); - app.UseSwaggerUi(config => - { - config.DocumentTitle = "TodoAPI"; - config.Path = "/swagger"; - config.DocumentPath = "/swagger/{documentName}/swagger.json"; - config.DocExpansion = "list"; - }); -} -// -// -app.MapGet("/todoitems", async (TodoDb db) => - await db.Todos.ToListAsync()); - -app.MapGet("/todoitems/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -// -app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); -// -// - -// -app.MapPost("/todoitems", async (Todo todo, TodoDb db) => -{ - db.Todos.Add(todo); - await db.SaveChangesAsync(); - - return Results.Created($"/todoitems/{todo.Id}", todo); -}); -// - -// -app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => -{ - var todo = await db.Todos.FindAsync(id); - - if (todo is null) return Results.NotFound(); - - todo.Name = inputTodo.Name; - todo.IsComplete = inputTodo.IsComplete; - - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); -// - -// -app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => -{ - if (await db.Todos.FindAsync(id) is Todo todo) - { - db.Todos.Remove(todo); - await db.SaveChangesAsync(); - return Results.NoContent(); - } - - return Results.NotFound(); -}); -// - -app.Run(); -// -#elif TYPEDR -using Microsoft.AspNetCore.Http.HttpResults; -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); -var app = builder.Build(); - -app.MapGet("/todoitems", async (TodoDb db) => - await db.Todos.ToListAsync()); - -app.MapGet("/todoitems/complete", async (TodoDb db) => - await db.Todos.Where(t => t.IsComplete).ToListAsync()); - -app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? Results.Ok(todo) - : Results.NotFound()); - -// - app.MapGet("/todos/{id}", async Task, NotFound>> (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(todo) - : TypedResults.NotFound()); -// - -/* -// -app.MapGet("/todos/{id}", async (int id, TodoDb db) => - await db.Todos.FindAsync(id) - is Todo todo - ? TypedResults.Ok(todo) - : TypedResults.NotFound()); -// -*/ - -// -app.MapGet("/hello", () => Results.Ok(new Message() { Text = "Hello World!" })) - .Produces(); -// - -// -app.MapGet("/hello2", () => TypedResults.Ok(new Message() { Text = "Hello World!" })); -// - -app.Run(); -#endif \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs deleted file mode 100644 index 86aba6a37cee..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/Todo.cs +++ /dev/null @@ -1,6 +0,0 @@ -public class Todo -{ - public int Id { get; set; } - public string? Name { get; set; } - public bool IsComplete { get; set; } -} \ No newline at end of file diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj deleted file mode 100644 index 067275c7128b..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoApi.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs deleted file mode 100644 index d202ecad4cc8..000000000000 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_SwaggerVersion/TodoDb.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -class TodoDb : DbContext -{ - public TodoDb(DbContextOptions options) - : base(options) { } - - public DbSet Todos => Set(); -} \ No newline at end of file From c6d9ea9341d95905406d4cc5a8424cb23a11e652 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 17:54:10 -0700 Subject: [PATCH 11/40] Updated app sample paths --- aspnetcore/tutorials/min-web-api.md | 60 +++++++++---------- .../TodoApi => TodoApi_VSC_Scalar}/Program.cs | 0 .../TodoApi => TodoApi_VSC_Scalar}/Todo.cs | 0 .../TodoApi.csproj | 0 .../TodoApi => TodoApi_VSC_Scalar}/TodoDb.cs | 0 .../TodoItemDTO.cs | 0 .../TodoPatchDto.cs | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../Program.cs | 0 .../Todo.cs | 0 .../TodoApi.csproj | 0 .../TodoApi.http | 0 .../TodoDb.cs | 0 .../TodoItemDTO.cs | 0 .../TodoPatchDto.cs | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 18 files changed, 30 insertions(+), 30 deletions(-) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VSC_Scalar}/Program.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/Todo.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/TodoApi.csproj (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/TodoDb.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/TodoItemDTO.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/TodoPatchDto.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/appsettings.Development.json (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VSC_Scalar}/appsettings.json (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VS_EndpointExplorer}/Program.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/Todo.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/TodoApi.csproj (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo/TodoApi => TodoApi_VS_EndpointExplorer}/TodoApi.http (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/TodoDb.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/TodoItemDTO.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/TodoPatchDto.cs (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/appsettings.Development.json (100%) rename aspnetcore/tutorials/min-web-api/samples/10.x/{todo_ScalarVersion/TodoApi => TodoApi_VS_EndpointExplorer}/appsettings.json (100%) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 8424701f073c..02aeb1632e91 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -88,11 +88,11 @@ The `Program.cs` file generated by the template contains the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_templatestart"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_templatestart"::: --- @@ -134,7 +134,7 @@ NuGet packages must be added to support the database and diagnostics used in thi * In the project folder, create a file named `Todo.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Todo.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Todo.cs"::: The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. @@ -142,7 +142,7 @@ The `Secret` property isn't used by the API's endpoints yet. It represents a com * Create a file named `TodoDb.cs` with the following code: - :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoDb.cs"::: + :::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/TodoDb.cs"::: The preceding code defines the *database context*, which is the main class that coordinates [Entity Framework](/ef/core/) functionality for a data model. This class derives from the class. @@ -156,11 +156,11 @@ The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_minimal_start_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_minimal_start_all"::: --- @@ -170,11 +170,11 @@ The following highlighted code adds the database context to the [dependency inje # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_DI&highlight=2-3)] +[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_DI&highlight=2-3)] # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_DI&highlight=2-3)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_DI&highlight=2-3)] --- @@ -202,7 +202,7 @@ In this tutorial, Scalar is used only for its API reference middleware, which re * In `Program.cs`, add the `using` directive and the highlighted `MapScalarApiReference` line inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: - [!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_scalar&highlight=4)] + [!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_scalar&highlight=4)] The preceding code enables the Scalar UI in Development only. It reads `/openapi/v1.json`, the document produced by `MapOpenApi()`, and serves the API reference at `/scalar/v1`. Be sure to add `using Scalar.AspNetCore;` to the top of the file. @@ -219,11 +219,11 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_post)] +[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_post)] # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_post)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_post)] --- @@ -321,11 +321,11 @@ Your `Program.cs` includes several GET endpoints, defined with `MapGet`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_get)] +[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_get)] # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_get)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_get)] --- @@ -445,11 +445,11 @@ The sample app implements a single PUT endpoint using `MapPut`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_put)] +[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_put)] # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_put)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_put)] --- @@ -523,7 +523,7 @@ The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to prope Create a file named `TodoPatchDto.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoPatchDto.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/TodoPatchDto.cs"::: The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to distinguish between a field that wasn't provided in the request versus a field explicitly set to a value. @@ -531,11 +531,11 @@ The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to dis # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_patch)] +[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_patch)] # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_patch)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_patch)] --- @@ -606,11 +606,11 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo/Program.cs?name=snippet_delete)] +[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_delete)] # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs?name=snippet_delete)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_delete)] --- @@ -653,11 +653,11 @@ Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs" id="snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_mapgroup_all"::: --- @@ -677,25 +677,25 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs" id="snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_typed_all"::: --- The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: These methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_typed_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -732,17 +732,17 @@ Verify you can post and get the `Secret` field with the current endpoints. Create a file named `TodoItemDTO.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/TodoItemDTO.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: Replace the contents of the `Program.cs` file with the following code to use this DTO model: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo/Program.cs" id="snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/Program.cs" id="snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_dto_all"::: --- diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Program.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Todo.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Todo.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Todo.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.csproj rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoDb.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoDb.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoDb.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoItemDTO.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoItemDTO.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoItemDTO.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoItemDTO.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoPatchDto.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoPatchDto.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoPatchDto.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoPatchDto.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.Development.json b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/appsettings.Development.json similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.Development.json rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/appsettings.Development.json diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.json b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/appsettings.json similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/appsettings.json rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/appsettings.json diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/Program.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Todo.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Todo.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/Todo.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Todo.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoApi.csproj rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.http b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.http similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo/TodoApi/TodoApi.http rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.http diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoDb.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoDb.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoDb.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoDb.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoItemDTO.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoItemDTO.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoPatchDto.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoPatchDto.cs similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/TodoPatchDto.cs rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoPatchDto.cs diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.Development.json b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/appsettings.Development.json similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.Development.json rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/appsettings.Development.json diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.json b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/appsettings.json similarity index 100% rename from aspnetcore/tutorials/min-web-api/samples/10.x/todo_ScalarVersion/TodoApi/appsettings.json rename to aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/appsettings.json From 5b0d15f15aa7e1b65a87e0bbdf2f187009a6580f Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 18:00:29 -0700 Subject: [PATCH 12/40] sample path corection --- aspnetcore/tutorials/min-web-api.md | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 02aeb1632e91..b4a40b10912e 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -88,7 +88,7 @@ The `Program.cs` file generated by the template contains the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_templatestart"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -134,7 +134,7 @@ NuGet packages must be added to support the database and diagnostics used in thi * In the project folder, create a file named `Todo.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Todo.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Todo.cs"::: The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. @@ -142,7 +142,7 @@ The `Secret` property isn't used by the API's endpoints yet. It represents a com * Create a file named `TodoDb.cs` with the following code: - :::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/TodoDb.cs"::: + :::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/TodoDb.cs"::: The preceding code defines the *database context*, which is the main class that coordinates [Entity Framework](/ef/core/) functionality for a data model. This class derives from the class. @@ -156,7 +156,7 @@ The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_minimal_start_all"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -170,7 +170,7 @@ The following highlighted code adds the database context to the [dependency inje # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_DI&highlight=2-3)] +[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_DI&highlight=2-3)] # [Visual Studio Code](#tab/visual-studio-code) @@ -219,7 +219,7 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_post)] +[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_post)] # [Visual Studio Code](#tab/visual-studio-code) @@ -321,7 +321,7 @@ Your `Program.cs` includes several GET endpoints, defined with `MapGet`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_get)] +[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_get)] # [Visual Studio Code](#tab/visual-studio-code) @@ -445,7 +445,7 @@ The sample app implements a single PUT endpoint using `MapPut`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_put)] +[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_put)] # [Visual Studio Code](#tab/visual-studio-code) @@ -523,7 +523,7 @@ The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to prope Create a file named `TodoPatchDto.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/TodoPatchDto.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/TodoPatchDto.cs"::: The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to distinguish between a field that wasn't provided in the request versus a field explicitly set to a value. @@ -531,7 +531,7 @@ The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to dis # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_patch)] +[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_patch)] # [Visual Studio Code](#tab/visual-studio-code) @@ -606,7 +606,7 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_delete)] +[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_delete)] # [Visual Studio Code](#tab/visual-studio-code) @@ -653,7 +653,7 @@ Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -677,7 +677,7 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -687,15 +687,15 @@ The `Map` methods can call route handler methods instead of using lamb The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: These methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -732,13 +732,13 @@ Verify you can post and get the `Secret` field with the current endpoints. Create a file named `TodoItemDTO.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: Replace the contents of the `Program.cs` file with the following code to use this DTO model: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples//TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: # [Visual Studio Code](#tab/visual-studio-code) From d377a43e9f44ae8a73d982cba29476836e8e7847 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 18:08:18 -0700 Subject: [PATCH 13/40] vs samples path fix in tutorial --- aspnetcore/tutorials/min-web-api.md | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index b4a40b10912e..9a17025fef77 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -88,7 +88,7 @@ The `Program.cs` file generated by the template contains the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_templatestart"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -134,7 +134,7 @@ NuGet packages must be added to support the database and diagnostics used in thi * In the project folder, create a file named `Todo.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Todo.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Todo.cs"::: The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. @@ -142,7 +142,7 @@ The `Secret` property isn't used by the API's endpoints yet. It represents a com * Create a file named `TodoDb.cs` with the following code: - :::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/TodoDb.cs"::: + :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoDb.cs"::: The preceding code defines the *database context*, which is the main class that coordinates [Entity Framework](/ef/core/) functionality for a data model. This class derives from the class. @@ -156,7 +156,7 @@ The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_minimal_start_all"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -170,7 +170,7 @@ The following highlighted code adds the database context to the [dependency inje # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_DI&highlight=2-3)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_DI&highlight=2-3)] # [Visual Studio Code](#tab/visual-studio-code) @@ -219,7 +219,7 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_post)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_post)] # [Visual Studio Code](#tab/visual-studio-code) @@ -321,7 +321,7 @@ Your `Program.cs` includes several GET endpoints, defined with `MapGet`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_get)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_get)] # [Visual Studio Code](#tab/visual-studio-code) @@ -445,7 +445,7 @@ The sample app implements a single PUT endpoint using `MapPut`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_put)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_put)] # [Visual Studio Code](#tab/visual-studio-code) @@ -523,7 +523,7 @@ The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to prope Create a file named `TodoPatchDto.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/TodoPatchDto.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoPatchDto.cs"::: The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to distinguish between a field that wasn't provided in the request versus a field explicitly set to a value. @@ -531,7 +531,7 @@ The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to dis # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_patch)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_patch)] # [Visual Studio Code](#tab/visual-studio-code) @@ -606,7 +606,7 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_delete)] +[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_delete)] # [Visual Studio Code](#tab/visual-studio-code) @@ -653,7 +653,7 @@ Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -677,7 +677,7 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: # [Visual Studio Code](#tab/visual-studio-code) @@ -687,15 +687,15 @@ The `Map` methods can call route handler methods instead of using lamb The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: These methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -732,13 +732,13 @@ Verify you can post and get the `Secret` field with the current endpoints. Create a file named `TodoItemDTO.cs` with the following code: -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: Replace the contents of the `Program.cs` file with the following code to use this DTO model: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: # [Visual Studio Code](#tab/visual-studio-code) From 5cbe05dfe6c451c4c1cc229bdec7fe19866728fd Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 22:07:35 -0700 Subject: [PATCH 14/40] Adding more snippet tags for Typed version --- aspnetcore/tutorials/min-web-api.md | 2 +- .../10.x/TodoApi_VS_EndpointExplorer/Program.cs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 9a17025fef77..45987e18e8d1 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -689,7 +689,7 @@ The `Map` code now calls methods instead of lambdas: :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: -These methods return objects that implement and are defined by : +These following methods return objects that implement and are defined by : :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs index c54e47801d51..964cdd6c88c7 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs @@ -114,6 +114,7 @@ is Todo todo // #elif WITHPATCH +// using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); @@ -190,7 +191,9 @@ is Todo todo app.Run(); +// #elif MAPGROUP +// using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); @@ -267,7 +270,9 @@ is Todo todo app.Run(); +// #elif TYPED +// using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); @@ -280,6 +285,7 @@ is Todo todo app.MapOpenApi(); } +// var todoItems = app.MapGroup("/todoitems"); todoItems.MapGet("/", GetAllTodos); @@ -290,12 +296,16 @@ is Todo todo todoItems.MapPatch("/{id}", PatchTodo); todoItems.MapDelete("/{id}", DeleteTodo); +// app.Run(); +// +// static async Task GetAllTodos(TodoDb db) { return TypedResults.Ok(await db.Todos.ToArrayAsync()); } +// static async Task GetCompleteTodos(TodoDb db) { @@ -358,6 +368,8 @@ static async Task DeleteTodo(int id, TodoDb db) return TypedResults.NotFound(); } +// +// #elif PREVENTOVERPOST using Microsoft.EntityFrameworkCore; @@ -456,4 +468,5 @@ static async Task DeleteTodo(int id, TodoDb db) return TypedResults.NotFound(); } +// #endif From fb4f65ea43d7740ee1b01c0f5bb9cc083036023b Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 22:26:30 -0700 Subject: [PATCH 15/40] Add snippet tags for Over-Posting example --- .../samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs index 964cdd6c88c7..b9455413a06b 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs @@ -285,7 +285,7 @@ is Todo todo app.MapOpenApi(); } -// +// var todoItems = app.MapGroup("/todoitems"); todoItems.MapGet("/", GetAllTodos); @@ -371,6 +371,7 @@ static async Task DeleteTodo(int id, TodoDb db) // // #elif PREVENTOVERPOST +// using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); @@ -468,5 +469,5 @@ static async Task DeleteTodo(int id, TodoDb db) return TypedResults.NotFound(); } -// +// #endif From c6bef6b378f3049d4b9647802724b1a115475ebe Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 22:58:18 -0700 Subject: [PATCH 16/40] Updated code snippet include formatting --- aspnetcore/tutorials/min-web-api.md | 52 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 45987e18e8d1..ec558129dde7 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -88,11 +88,11 @@ The `Program.cs` file generated by the template contains the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_templatestart"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_templatestart"::: --- @@ -156,11 +156,11 @@ The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_minimal_start_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_minimal_start_all"::: --- @@ -170,11 +170,11 @@ The following highlighted code adds the database context to the [dependency inje # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_DI&highlight=2-3)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_DI" highlight="2-3"::: # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_DI&highlight=2-3)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_DI" highlight="2-3"::: --- @@ -202,7 +202,7 @@ In this tutorial, Scalar is used only for its API reference middleware, which re * In `Program.cs`, add the `using` directive and the highlighted `MapScalarApiReference` line inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: - [!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_scalar&highlight=4)] + :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_scalar" highlight="4"::: The preceding code enables the Scalar UI in Development only. It reads `/openapi/v1.json`, the document produced by `MapOpenApi()`, and serves the API reference at `/scalar/v1`. Be sure to add `using Scalar.AspNetCore;` to the top of the file. @@ -219,11 +219,11 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_post)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_post"::: # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_post)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_post"::: --- @@ -321,11 +321,11 @@ Your `Program.cs` includes several GET endpoints, defined with `MapGet`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_get)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_get"::: # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_get)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_get"::: --- @@ -445,11 +445,11 @@ The sample app implements a single PUT endpoint using `MapPut`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_put)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_put"::: # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_put)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_put"::: --- @@ -531,11 +531,11 @@ The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to dis # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_patch)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_patch"::: # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_patch)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_patch"::: --- @@ -606,11 +606,11 @@ Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio](#tab/visual-studio) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs?name=snippet_delete)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_delete"::: # [Visual Studio Code](#tab/visual-studio-code) -[!code-csharp[](~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs?name=snippet_delete)] +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_delete"::: --- @@ -653,11 +653,11 @@ Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_mapgroup_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_mapgroup_all"::: --- @@ -677,25 +677,25 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_typed_all"::: --- The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_group"::: These following methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -738,11 +738,11 @@ Replace the contents of the `Program.cs` file with the following code to use thi # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_dto_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_dto_all"::: --- From 8d779b0700547ecc9ba0c13a8bdb8f2e425dcad4 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Sun, 28 Jun 2026 23:24:54 -0700 Subject: [PATCH 17/40] Additonal edits per style guide. --- aspnetcore/tutorials/min-web-api.md | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index ec558129dde7..9a63f5b7519f 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -17,7 +17,7 @@ By [Wade Pickett](https://github.com/wadepickett) and [Tom Dykstra](https://gith :::moniker range=">= aspnetcore-10.0" -Minimal APIs are architected to create HTTP APIs with minimal dependencies. They're ideal for microservices and apps that want to include only the minimum files, features, and dependencies in ASP.NET Core. +Minimal APIs are designed to create HTTP APIs with minimal dependencies. They're ideal for microservices and apps that want to include only the minimum files, features, and dependencies in ASP.NET Core. This tutorial teaches the basics of building a Minimal API with ASP.NET Core. Another approach to creating APIs in ASP.NET Core is to use controllers. For help with choosing between Minimal APIs and controller-based APIs, see . For a tutorial on creating an API project based on [controllers](xref:web-api/index) that contains more features, see [Create a web API](xref:tutorials/first-web-api). @@ -58,7 +58,7 @@ This tutorial creates the following API: * In the **Additional information** dialog: * Confirm the **Framework** is **.NET 10.0 (Long Term Support)**. * Confirm the checkbox for **Enable OpenAPI support** is checked. - * Confirm the checkbox for **Use controllers** is **not** checked. Unchecking this setting creates a Minimal API project as required for this tutorial rather than a controller-based one. + * Confirm the checkbox for **Use controllers** is **not** checked. Uncheck this setting to create a Minimal API project as required for this tutorial rather than a controller-based one. * Select **Create**. ![Additional information](~/tutorials/min-web-api/static/10/add-information-dialog-18-7-1.png) @@ -66,7 +66,7 @@ This tutorial creates the following API: # [Visual Studio Code](#tab/visual-studio-code) * Open the [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal). -* Change directories (`cd`) to the folder that will contain the project folder. +* Change directories (`cd`) to the folder that contains the project folder. * Run the following commands: ```dotnetcli @@ -99,15 +99,15 @@ The `Program.cs` file generated by the template contains the following code: The preceding code: * Creates a and a with preconfigured defaults. -* Registers the in-box OpenAPI document generator with `builder.Services.AddOpenApi()`. -* Maps the generated OpenAPI document at `/openapi/v1.json` with `app.MapOpenApi()`, in the Development environment only. +* Registers the in-box OpenAPI document generator by using `builder.Services.AddOpenApi()`. +* Maps the generated OpenAPI document at `/openapi/v1.json` by using `app.MapOpenApi()`, in the Development environment only. * Defines a sample `GET /weatherforecast` endpoint that returns five randomly generated `WeatherForecast` records. -In this tutorial, you'll replace the `WeatherForecast` with a new Todo sample, with endpoints to create, read, update, and delete items, backed by a model and a database. +In this tutorial, you replace the `WeatherForecast` with a new Todo sample, with endpoints to create, read, update, and delete items, backed by a model and a database. ## Add NuGet packages -NuGet packages must be added to support the database and diagnostics used in this tutorial. +Add NuGet packages to support the database and diagnostics used in this tutorial. # [Visual Studio](#tab/visual-studio) @@ -138,7 +138,7 @@ NuGet packages must be added to support the database and diagnostics used in thi The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. -The `Secret` property isn't used by the API's endpoints yet. It represents a common real-world need: data the app stores and uses internally, such as the ID of the user who owns the item, that you don't want clients to see or set. In the [Prevent over-posting](#prevent-over-posting) step later in this tutorial, you'll use a Data Transfer Object (DTO) to keep fields like `Secret` out of the API's input and responses. +The `Secret` property isn't used by the API's endpoints yet. It represents a common real-world need: data the app stores and uses internally, such as the ID of the user who owns the item, that you don't want clients to see or set. In the [Prevent over-posting](#prevent-over-posting) step later in this tutorial, you use a Data Transfer Object (DTO) to keep fields like `Secret` out of the API's input and responses. * Create a file named `TodoDb.cs` with the following code: @@ -150,7 +150,7 @@ The app uses an in-memory database named `TodoList`. The database is registered ## Replace the WeatherForecast sample with the Todo API -The `webapi` template added a sample `GET /weatherforecast` endpoint to `Program.cs` and a `WeatherForecast` record at the bottom of the file. The sample is just a placeholder to show the template works — replace both with the Todo endpoints below. +The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program.cs` and a `WeatherForecast` record at the bottom of the file. The sample is just a placeholder to show the template works - replace both with the Todo endpoints described in the following section. * In `Program.cs`, replace the `WeatherForecast` sample endpoint and the `WeatherForecast` record with the following code: @@ -229,7 +229,7 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th Run the app. The browser displays a 404 error because there's no longer a `/` endpoint. -The POST endpoint will be used to add data to the app. +Use the POST endpoint to add data to the app. # [Visual Studio](#tab/visual-studio) @@ -293,8 +293,8 @@ The POST endpoint will be used to add data to the app. * With the app still running, in the browser, navigate to `https://localhost:{port}/scalar/v1` to display the API reference page generated by Scalar. -* On the Scalar page, select the **POST /todoitems** operation, then select **Test Request**. -* In the request body enter JSON for a to-do item, without specifying the optional `id`: +* On the Scalar page, select the **POST /todoitems** operation, and then select **Test Request**. +* In the request body, enter JSON for a to-do item without specifying the optional `id`: ```json { @@ -305,7 +305,7 @@ The POST endpoint will be used to add data to the app. * Select **Send**. -The Scalar UI displays the response, including the status code and response body. The response body shows the `id` was set to `1`. A 201 `HTTP` status code is returned, indicating that the request was successfully processed and resulted in the creation of a new resource. +The Scalar UI displays the response, including the status code and response body. The response body shows the `id` is set to `1`. A 201 `HTTP` status code is returned, which indicates that the request was successfully processed and resulted in the creation of a new resource. --- @@ -394,7 +394,7 @@ Test the app by calling the endpoints from a browser or the Scalar UI. * In the Scalar UI, select **GET /todoitems**, then **Test Request** > **Send**. -* Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems`. For example, `http://localhost:7032/todoitems` +* Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems`. For example, `http://localhost:7032/todoitems`. The call to `GET /todoitems` produces a response similar to the following: @@ -410,10 +410,10 @@ The call to `GET /todoitems` produces a response similar to the following: ``` * Call **GET /todoitems/{id}** in Scalar to return data from a specific id: - * Select **GET /todoitems/{id}**, then **Test Request**. + * Select **GET /todoitems/{id}**, and then select **Test Request**. * Set the **id** field to `1` and select **Send**. -* Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems/1`. For example, `http://localhost:7032/todoitems/1` +* Alternatively, call **GET /todoitems/{id}** from a browser by entering the URI `http://localhost:{port}/todoitems/1`. For example, `http://localhost:7032/todoitems/1`. * The response is similar to the following: @@ -428,7 +428,7 @@ The call to `GET /todoitems` produces a response similar to the following: --- -This app uses an in-memory database. If the app is restarted, the data is lost: `GET /todoitems` returns an empty array (`[]`), and `GET /todoitems/{id}` returns a `404 Not Found`. To repopulate the app, [POST](#post) data to the app and try the GET request again. +This app uses an in-memory database. If you restart the app, the data is lost: `GET /todoitems` returns an empty array (`[]`), and `GET /todoitems/{id}` returns a `404 Not Found`. To repopulate the app, [POST](#post) data to the app and try the GET request again. ## Return values @@ -497,7 +497,7 @@ Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. Use the Scalar UI to send a PUT request: -* Select **PUT /todoitems/{id}**, then **Test Request**. +* Select **PUT /todoitems/{id}**, and then select **Test Request**. * Set the **id** field to `1`. @@ -517,9 +517,9 @@ Use the Scalar UI to send a PUT request: ## Create and examine the PATCH endpoint -A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This differs from a PUT request which replaces the entire item, so the client must send every field even to change just one. +A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. -The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. Using nullable properties allows the endpoint to distinguish between a field that wasn't provided (null) versus a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool would default to false, potentially overwriting an existing true value when that field wasn't included in the request. +The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided (null) and a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool defaults to false, which could potentially overwrite an existing true value when that field isn't included in the request. Create a file named `TodoPatchDto.cs` with the following code: @@ -539,7 +539,7 @@ The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to dis --- -This method is similar to the `MapPut` method, except it uses HTTP PATCH and only updates the fields provided in the request. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). +This method is similar to the `MapPut` method, but it uses HTTP PATCH and only updates the fields provided in the request. A successful response returns [204 (No Content)](https://www.rfc-editor.org/rfc/rfc9110#status.204). > [!NOTE] > PATCH operations allow partial updates to resources. For more advanced partial updates using JSON Patch documents, see . @@ -584,7 +584,7 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n Use the Scalar UI to send a PATCH request: -* Select **PATCH /todoitems/{id}**, then **Test Request**. +* Select **PATCH /todoitems/{id}**, and then select **Test Request**. * Set the **id** field to `1`. @@ -602,7 +602,7 @@ Use the Scalar UI to send a PATCH request: ## Examine the DELETE endpoint -Your `Program.cs` includes a single DELETE endpoint, defined with `MapDelete`: +Your `Program.cs` file includes a single DELETE endpoint, defined with `MapDelete`: # [Visual Studio](#tab/visual-studio) @@ -647,7 +647,7 @@ Use the Scalar UI to send a DELETE request: ## Use the MapGroup API -The `Program.cs` you wrote repeats the `todoitems` URL prefix each time it sets up an endpoint. APIs often have groups of endpoints with a common URL prefix, and the method is available to help organize such groups. It reduces repetitive code and allows for customizing entire groups of endpoints with a single call to methods like and . +The `Program.cs` file you wrote repeats the `todoitems` URL prefix each time it sets up an endpoint. APIs often have groups of endpoints with a common URL prefix, and the method helps organize such groups. It reduces repetitive code and allows you to customize entire groups of endpoints with a single call to methods like and . Replace the contents of `Program.cs` with the following code: @@ -719,16 +719,16 @@ public async Task GetAllTodos_ReturnsOkOfTodosResult() Currently your API exposes the entire `Todo` object, including the `Secret` property you added in [The model and database context classes](#model-db-classes). In production applications, a subset of the model is often used to restrict the data that can be input and returned. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. **DTO** is used in this article. -A DTO can be used to: +Use a DTO to: * Prevent over-posting. * Hide properties that clients aren't supposed to view. * Omit some properties to reduce payload size. * Flatten object graphs that contain nested objects. Flattened object graphs can be more convenient for clients. -The `Secret` field needs to be hidden from this app, but an administrative app could choose to expose it. +This app needs to hide the `Secret` field, but an administrative app could choose to expose it. -Verify you can post and get the `Secret` field with the current endpoints. +Verify you can post and get the `Secret` field by using the current endpoints. Create a file named `TodoItemDTO.cs` with the following code: From 9a013e60a404145a1a6ff9f402df642b5e9586b6 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 14:10:26 -0700 Subject: [PATCH 18/40] fixed code link format --- aspnetcore/tutorials/min-web-api.md | 52 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 9a63f5b7519f..7ba7b3be9a7f 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -88,11 +88,11 @@ The `Program.cs` file generated by the template contains the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_templatestart"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_templatestart"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_templatestart"::: --- @@ -156,11 +156,11 @@ The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program. # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_minimal_start_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_minimal_start_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_minimal_start_all"::: --- @@ -170,11 +170,11 @@ The following highlighted code adds the database context to the [dependency inje # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_DI" highlight="2-3"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_DI" highlight="2-3"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_DI" highlight="2-3"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_DI" highlight="2-3"::: --- @@ -202,7 +202,7 @@ In this tutorial, Scalar is used only for its API reference middleware, which re * In `Program.cs`, add the `using` directive and the highlighted `MapScalarApiReference` line inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: - :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_scalar" highlight="4"::: + :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_scalar" highlight="4"::: The preceding code enables the Scalar UI in Development only. It reads `/openapi/v1.json`, the document produced by `MapOpenApi()`, and serves the API reference at `/scalar/v1`. Be sure to add `using Scalar.AspNetCore;` to the top of the file. @@ -219,11 +219,11 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_post"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_post"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_post"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_post"::: --- @@ -321,11 +321,11 @@ Your `Program.cs` includes several GET endpoints, defined with `MapGet`: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_get"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_get"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_get"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_get"::: --- @@ -445,11 +445,11 @@ The sample app implements a single PUT endpoint using `MapPut`: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_put"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_put"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_put"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_put"::: --- @@ -531,11 +531,11 @@ The `TodoPatchDto` class uses nullable properties (`string?` and `bool?`) to dis # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_patch"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_patch"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_patch"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_patch"::: --- @@ -606,11 +606,11 @@ Your `Program.cs` file includes a single DELETE endpoint, defined with `MapDelet # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_delete"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_delete"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_delete"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_delete"::: --- @@ -653,11 +653,11 @@ Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_mapgroup_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_mapgroup_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_mapgroup_all"::: --- @@ -677,25 +677,25 @@ The `Map` methods can call route handler methods instead of using lamb # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_typed_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_typed_all"::: --- The `Map` code now calls methods instead of lambdas: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_group"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: These following methods return objects that implement and are defined by : -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_handlers"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: Unit tests can call these methods and test that they return the correct type. For example, if the method is `GetAllTodos`: -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_typed_getalltodos"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_getalltodos"::: Unit test code can verify that an object of type [Ok\](xref:Microsoft.AspNetCore.Http.HttpResults.Ok%601.Value) is returned from the handler method. For example: @@ -738,11 +738,11 @@ Replace the contents of the `Program.cs` file with the following code to use thi # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="name=snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_dto_all"::: # [Visual Studio Code](#tab/visual-studio-code) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="name=snippet_dto_all"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_dto_all"::: --- From 3aeaf53b84053f84959acac01f130c9013d45aa5 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 15:19:40 -0700 Subject: [PATCH 19/40] Removed AddDatabaseDeveloperPageExceptionFilter() since InMemory only is used --- aspnetcore/tutorials/min-web-api.md | 8 +++----- .../samples/10.x/TodoApi_VSC_Scalar/Program.cs | 5 ----- .../samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj | 1 - .../10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj | 1 - 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 7ba7b3be9a7f..da54c03238ac 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -107,7 +107,7 @@ In this tutorial, you replace the `WeatherForecast` with a new Todo sample, with ## Add NuGet packages -Add NuGet packages to support the database and diagnostics used in this tutorial. +Add NuGet packages to support the database used in this tutorial. # [Visual Studio](#tab/visual-studio) @@ -115,15 +115,13 @@ Add NuGet packages to support the database and diagnostics used in this tutorial * Select the **Browse** tab. * Enter **Microsoft.EntityFrameworkCore.InMemory** in the search box, and then select `Microsoft.EntityFrameworkCore.InMemory`. * Select the **Project** checkbox in the right pane and then select **Install**. -* Follow the preceding instructions to add the `Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore` package. # [Visual Studio Code](#tab/visual-studio-code) -* Run the following commands: +* Run the following command: ```dotnetcli dotnet add package Microsoft.EntityFrameworkCore.InMemory - dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore ``` --- @@ -170,7 +168,7 @@ The following highlighted code adds the database context to the [dependency inje # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_DI" highlight="2-3"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_DI" highlight="2"::: # [Visual Studio Code](#tab/visual-studio-code) diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs index 12ea67824c2a..09dc9665a583 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs @@ -52,7 +52,6 @@ internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary // var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddOpenApi(); var app = builder.Build(); // @@ -129,7 +128,6 @@ is Todo todo var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddOpenApi(); var app = builder.Build(); @@ -211,7 +209,6 @@ is Todo todo var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddOpenApi(); var app = builder.Build(); @@ -293,7 +290,6 @@ is Todo todo var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddOpenApi(); var app = builder.Build(); @@ -395,7 +391,6 @@ static async Task DeleteTodo(int id, TodoDb db) var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); -builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddOpenApi(); var app = builder.Build(); diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj index 0f463c5c9ea5..a336ed7d8b27 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/TodoApi.csproj @@ -7,7 +7,6 @@ - diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj index 0f463c5c9ea5..a336ed7d8b27 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoApi.csproj @@ -7,7 +7,6 @@ - From 17f46b99c5e4a28a323dcf88c6d9f47743049d21 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 15:49:26 -0700 Subject: [PATCH 20/40] Replace missing AddOpenAPI line in code --- .../samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs index b9455413a06b..9d278f807641 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs @@ -51,6 +51,7 @@ internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary // var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList")); +builder.Services.AddOpenApi(); var app = builder.Build(); // From 0440dd3727ba32fadc2e9059ed29a07ee3194651 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 16:10:17 -0700 Subject: [PATCH 21/40] Removed text related to diagnostics --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index da54c03238ac..bcebad66ba36 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -164,7 +164,7 @@ The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program. The OpenAPI lines added by the template (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) remain in place. They now describe the Todo endpoints instead of the sample weather endpoint. -The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container and enables displaying database-related exceptions: +The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container: # [Visual Studio](#tab/visual-studio) From b1a09d989926e8577aa7794211de0eb9346de98a Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 16:42:21 -0700 Subject: [PATCH 22/40] Put MapOpenAPI back in. --- aspnetcore/tutorials/min-web-api.md | 4 ++-- .../samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index bcebad66ba36..385e134dfe4d 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -136,7 +136,7 @@ Add NuGet packages to support the database used in this tutorial. The preceding code creates the model for this app. A *model* is a class that represents data that the app manages. -The `Secret` property isn't used by the API's endpoints yet. It represents a common real-world need: data the app stores and uses internally, such as the ID of the user who owns the item, that you don't want clients to see or set. In the [Prevent over-posting](#prevent-over-posting) step later in this tutorial, you use a Data Transfer Object (DTO) to keep fields like `Secret` out of the API's input and responses. +The `Secret` property is included to demonstrate a common real-world need: data the app stores and uses internally, such as the ID of the user who owns the item, that you don't want clients to see or set. In the [Prevent over-posting](#prevent-over-posting) step later in this tutorial, you use a Data Transfer Object (DTO) to keep fields like `Secret` out of the API's input and responses. * Create a file named `TodoDb.cs` with the following code: @@ -150,7 +150,7 @@ The app uses an in-memory database named `TodoList`. The database is registered The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program.cs` and a `WeatherForecast` record at the bottom of the file. The sample is just a placeholder to show the template works - replace both with the Todo endpoints described in the following section. -* In `Program.cs`, replace the `WeatherForecast` sample endpoint and the `WeatherForecast` record with the following code: +* Replace all of the code in `Program.cs` with the following. The `WeatherForecast` sample endpoint and record are removed, and the Todo endpoints take their place: # [Visual Studio](#tab/visual-studio) diff --git a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs index 9d278f807641..7883c5ad9c17 100644 --- a/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs +++ b/aspnetcore/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs @@ -55,6 +55,11 @@ internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary var app = builder.Build(); // +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); +} + // app.MapGet("/todoitems", async (TodoDb db) => await db.Todos.ToListAsync()); From ce97d77ebb7319f660b0e9a3d7d2263b047823bf Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 18:20:19 -0700 Subject: [PATCH 23/40] Add new post ui image --- aspnetcore/tutorials/min-web-api.md | 9 +++++---- .../static/10/generate-request-vs18-6-2.png | Bin 0 -> 55717 bytes 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 aspnetcore/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 385e134dfe4d..4ff7a5fb0a29 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -225,18 +225,19 @@ The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` th --- -Run the app. The browser displays a 404 error because there's no longer a `/` endpoint. - -Use the POST endpoint to add data to the app. # [Visual Studio](#tab/visual-studio) * Press Ctrl+F5 to run the app without debugging. Visual Studio launches the [Kestrel web server](xref:fundamentals/servers/kestrel) and trusts the development certificate if needed. +[!INCLUDE[](~/includes/trustCertVS26.md)] + +Use the POST endpoint to add data to the app. + * Select **View** > **Other Windows** > **Endpoints Explorer**. * Right-click the **POST** endpoint and select **Generate request**. - ![Endpoints Explorer context menu highlighting Generate Request menu item.](~/tutorials/min-web-api/static/9.x/generate-request-vs17.8.0.png) + ![Endpoints Explorer context menu highlighting Generate Request menu item.](~/tutorials/min-web-api/static/10.x/generate-request-vs18-6-2.png) A new file is created in the project folder named `TodoApi.http`, with contents similar to the following example: diff --git a/aspnetcore/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png b/aspnetcore/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png new file mode 100644 index 0000000000000000000000000000000000000000..02e77ceeb651f37ac6537fea6d2c8e5646249608 GIT binary patch literal 55717 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 xUu`9U;%f4^B0J{sj5i=%@Le! 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 Q(HY=%6=4W3)3m++Kl Date: Mon, 29 Jun 2026 21:55:36 -0700 Subject: [PATCH 24/40] Add screenshot link --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 4ff7a5fb0a29..3a544087e4ed 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -237,7 +237,7 @@ Use the POST endpoint to add data to the app. * Select **View** > **Other Windows** > **Endpoints Explorer**. * Right-click the **POST** endpoint and select **Generate request**. - ![Endpoints Explorer context menu highlighting Generate Request menu item.](~/tutorials/min-web-api/static/10.x/generate-request-vs18-6-2.png) + ![Endpoints Explorer context menu highlighting Generate Request menu item.](~/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png) A new file is created in the project folder named `TodoApi.http`, with contents similar to the following example: From e465cc88bc1428d4629cb0190b49b87d4d3e511b Mon Sep 17 00:00:00 2001 From: wadepickett Date: Mon, 29 Jun 2026 23:21:49 -0700 Subject: [PATCH 25/40] Add screenshot link and stop instructions for patch secton --- aspnetcore/tutorials/min-web-api.md | 31 ++++++++++++++++-- ...tp-file-window-with-response-vs18-6-2.png} | Bin 2 files changed, 29 insertions(+), 2 deletions(-) rename aspnetcore/tutorials/min-web-api/static/10/{generate-request-vs18-6-2.png => http-file-window-with-response-vs18-6-2.png} (100%) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 3a544087e4ed..b271b327d621 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -286,7 +286,7 @@ Use the POST endpoint to add data to the app. The POST request is sent to the app and the response is displayed in the **Response** pane. - ![.http file window with response from the POST request.](~/tutorials/min-web-api/static/9.x/http-file-window-with-response-vs17.8.0.png) + ![.http file window with response from the POST request.](~/tutorials/min-web-api/static/10/http-file-window-with-response-vs18-6-2.png) # [Visual Studio Code](#tab/visual-studio-code) @@ -516,7 +516,23 @@ Use the Scalar UI to send a PUT request: ## Create and examine the PATCH endpoint -A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. +A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. + +The next steps add a new file and modify `Program.cs`, so stop the app before making these changes. + +# [Visual Studio](#tab/visual-studio) + +* To stop the app, select the **Stop** button (the red square) in the Visual Studio toolbar. + +# [Visual Studio Code](#tab/visual-studio-code) + +* To stop the app, press Ctrl+C in the integrated terminal where the app is running. + +--- + +The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided and a field explicitly set to a value. + +This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PATCH call. Call GET to ensure there's an item in the database before making a PATCH call. The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided (null) and a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool defaults to false, which could potentially overwrite an existing true value when that field isn't included in the request. @@ -545,6 +561,17 @@ This method is similar to the `MapPut` method, but it uses HTTP PATCH and only u ## Test the PATCH endpoint +# [Visual Studio](#tab/visual-studio) + +* Press Ctrl+F5 to rebuild and run the app with the new PATCH endpoint. + +# [Visual Studio Code](#tab/visual-studio-code) + +* Run the app again so it rebuilds with the new PATCH endpoint. + +--- + + This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PATCH call. Call GET to ensure there's an item in the database before making a PATCH call. Update only the `name` property of the Todo item that has `Id = 1` and set its name to `"run errands"`. diff --git a/aspnetcore/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png b/aspnetcore/tutorials/min-web-api/static/10/http-file-window-with-response-vs18-6-2.png similarity index 100% rename from aspnetcore/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png rename to aspnetcore/tutorials/min-web-api/static/10/http-file-window-with-response-vs18-6-2.png From 619842cc0607a93605dde9e344697e333327a4bb Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 17:09:30 -0700 Subject: [PATCH 26/40] Add stop and start instruction between sections --- aspnetcore/tutorials/min-web-api.md | 43 ++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index b271b327d621..95b41ef01420 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -290,6 +290,13 @@ Use the POST endpoint to add data to the app. # [Visual Studio Code](#tab/visual-studio-code) +[!INCLUDE[](~/includes/trustCertVSC.md)] + +* In Visual Studio Code, press Ctrl+F5 (Windows) or control+F5 (macOS) to run the app without debugging. + +The default browser launches with the following URL: `https://localhost:{PORT}` where `{PORT}` is the randomly generated port number. + + * With the app still running, in the browser, navigate to `https://localhost:{port}/scalar/v1` to display the API reference page generated by Scalar. * On the Scalar page, select the **POST /todoitems** operation, and then select **Test Request**. @@ -518,7 +525,7 @@ Use the Scalar UI to send a PUT request: A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. -The next steps add a new file and modify `Program.cs`, so stop the app before making these changes. +The next steps add a new file and modifies the `Program.cs file, so stop the app before making these changes. # [Visual Studio](#tab/visual-studio) @@ -536,7 +543,7 @@ This sample uses an in-memory database that must be initialized each time the ap The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided (null) and a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool defaults to false, which could potentially overwrite an existing true value when that field isn't included in the request. -Create a file named `TodoPatchDto.cs` with the following code: +* Create a file named `TodoPatchDto.cs` with the following code: :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoPatchDto.cs"::: @@ -567,7 +574,7 @@ This method is similar to the `MapPut` method, but it uses HTTP PATCH and only u # [Visual Studio Code](#tab/visual-studio-code) -* Run the app again so it rebuilds with the new PATCH endpoint. +* Run the app again so it rebuilds with the new PATCH endpoint. In Visual Studio Code, press Ctrl+F5 (Windows) or control+F5 (macOS) to run the app without debugging. --- @@ -578,7 +585,7 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n # [Visual Studio](#tab/visual-studio) -* In **Endpoints Explorer**, right-click the **PATCH** endpoint, and select **Generate request**. +* In **Endpoints Explorer**, select the refresh button, then right-click the **PATCH** endpoint, and select **Generate request**. The following content is added to the `TodoApi.http` file: @@ -673,9 +680,21 @@ Use the Scalar UI to send a DELETE request: ## Use the MapGroup API +* The next steps modifies the `Program.cs` file, so stop the app before making these changes. + +# [Visual Studio](#tab/visual-studio) + +* To stop the app, select the **Stop** button (the red square) in the Visual Studio toolbar. + +# [Visual Studio Code](#tab/visual-studio-code) + +* To stop the app, press Ctrl+C in the integrated terminal where the app is running. + +--- + The `Program.cs` file you wrote repeats the `todoitems` URL prefix each time it sets up an endpoint. APIs often have groups of endpoints with a common URL prefix, and the method helps organize such groups. It reduces repetitive code and allows you to customize entire groups of endpoints with a single call to methods like and . -Replace the contents of `Program.cs` with the following code: +* Replace the contents of `Program.cs` with the following code: # [Visual Studio](#tab/visual-studio) @@ -693,13 +712,15 @@ The preceding code has the following changes: * Changes all the `app.Map` methods to `todoItems.Map`. * Removes the URL prefix `/todoitems` from the `Map` method calls. -Test the endpoints to verify that they work the same. +* Run the app and test the endpoints to verify that they work the same. ## Use the TypedResults API +The next steps modifies the `Program.cs` file, so stop the app before making these changes. + Returning rather than has several advantages, including testability and automatically returning the response type metadata for OpenAPI to describe the endpoint. For more information, see [TypedResults vs Results](/aspnet/core/fundamentals/minimal-apis/responses#typedresults-vs-results). -The `Map` methods can call route handler methods instead of using lambdas. To see an example, update *Program.cs* with the following code: +* The `Map` methods can call route handler methods instead of using lambdas. To see an example, update *Program.cs* with the following code: # [Visual Studio](#tab/visual-studio) @@ -754,13 +775,15 @@ Use a DTO to: This app needs to hide the `Secret` field, but an administrative app could choose to expose it. -Verify you can post and get the `Secret` field by using the current endpoints. +* The next steps add a file, so stop the app before making these changes. + +--- Create a file named `TodoItemDTO.cs` with the following code: :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: -Replace the contents of the `Program.cs` file with the following code to use this DTO model: +* Replace the contents of the `Program.cs` file with the following code to use this DTO model: # [Visual Studio](#tab/visual-studio) @@ -772,7 +795,7 @@ Replace the contents of the `Program.cs` file with the following code to use thi --- -Verify you can post and get all fields except the `Secret` field. +* Run the app and verify you can post and get all fields except the `Secret` field. From 903dfcb38e5f7c8bccb431d7c49f52b2835a5807 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 17:23:56 -0700 Subject: [PATCH 27/40] Add generate request image --- aspnetcore/tutorials/min-web-api.md | 2 +- .../static/10/generate-request-vs17-8-0.png | Bin 0 -> 25414 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 aspnetcore/tutorials/min-web-api/static/10/generate-request-vs17-8-0.png diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 95b41ef01420..6558a814b39b 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -237,7 +237,7 @@ Use the POST endpoint to add data to the app. * Select **View** > **Other Windows** > **Endpoints Explorer**. * Right-click the **POST** endpoint and select **Generate request**. - ![Endpoints Explorer context menu highlighting Generate Request menu item.](~/tutorials/min-web-api/static/10/generate-request-vs18-6-2.png) + ![Endpoints Explorer context menu highlighting Generate Request menu item.](~/tutorials/min-web-api/static/10/generate-request-vs17-8-0.png) A new file is created in the project folder named `TodoApi.http`, with contents similar to the following example: diff --git a/aspnetcore/tutorials/min-web-api/static/10/generate-request-vs17-8-0.png b/aspnetcore/tutorials/min-web-api/static/10/generate-request-vs17-8-0.png new file mode 100644 index 0000000000000000000000000000000000000000..9434776fd525db4d096088fb29eb702337f390af GIT binary patch literal 25414 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 literal 0 HcmV?d00001 From 333f2ffb2a3ccc6bba7e86a8357d51fc261640a2 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 18:55:49 -0700 Subject: [PATCH 28/40] General edits to follow style guide --- aspnetcore/tutorials/min-web-api.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 6558a814b39b..f50e153e799c 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -162,7 +162,7 @@ The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program. --- -The OpenAPI lines added by the template (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) remain in place. They now describe the Todo endpoints instead of the sample weather endpoint. +The OpenAPI lines that the template adds (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) stay in place. They now describe the Todo endpoints instead of the sample weather endpoint. The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container: @@ -398,7 +398,7 @@ Test the app by calling the `GET` endpoints from a browser or by using **Endpoin Test the app by calling the endpoints from a browser or the Scalar UI. -* In the Scalar UI, select **GET /todoitems**, then **Test Request** > **Send**. +* In the Scalar UI, select **GET /todoitems**, and then select **Test Request** > **Send**. * Alternatively, call **GET /todoitems** from a browser by entering the URI `http://localhost:{port}/todoitems`. For example, `http://localhost:7032/todoitems`. @@ -463,7 +463,7 @@ This method is similar to the `MapPost` method, except it uses HTTP PUT. A succe ## Test the PUT endpoint -This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call. +This sample uses an in-memory database that you must initialize each time you start the app. You need an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call. Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. @@ -525,7 +525,7 @@ Use the Scalar UI to send a PUT request: A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. -The next steps add a new file and modifies the `Program.cs file, so stop the app before making these changes. +The next steps add a new file and modify the `Program.cs` file. Stop the app before making these changes. # [Visual Studio](#tab/visual-studio) @@ -539,7 +539,7 @@ The next steps add a new file and modifies the `Program.cs file, so stop the app The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided and a field explicitly set to a value. -This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PATCH call. Call GET to ensure there's an item in the database before making a PATCH call. +This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call GET to ensure the database has an item before making a PATCH call. The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided (null) and a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool defaults to false, which could potentially overwrite an existing true value when that field isn't included in the request. @@ -579,13 +579,13 @@ This method is similar to the `MapPut` method, but it uses HTTP PATCH and only u --- -This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PATCH call. Call GET to ensure there's an item in the database before making a PATCH call. +This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call GET to ensure the database has an item before making a PATCH call. Update only the `name` property of the Todo item that has `Id = 1` and set its name to `"run errands"`. # [Visual Studio](#tab/visual-studio) -* In **Endpoints Explorer**, select the refresh button, then right-click the **PATCH** endpoint, and select **Generate request**. +* In **Endpoints Explorer**, select the refresh button. Then, right-click the **PATCH** endpoint, and select **Generate request**. The following content is added to the `TodoApi.http` file: @@ -680,7 +680,7 @@ Use the Scalar UI to send a DELETE request: ## Use the MapGroup API -* The next steps modifies the `Program.cs` file, so stop the app before making these changes. +* The next steps modify the `Program.cs` file, so stop the app before making these changes. # [Visual Studio](#tab/visual-studio) @@ -716,7 +716,7 @@ The preceding code has the following changes: ## Use the TypedResults API -The next steps modifies the `Program.cs` file, so stop the app before making these changes. +The next steps modify the `Program.cs` file, so stop the app before making these changes. Returning rather than has several advantages, including testability and automatically returning the response type metadata for OpenAPI to describe the endpoint. For more information, see [TypedResults vs Results](/aspnet/core/fundamentals/minimal-apis/responses#typedresults-vs-results). @@ -764,7 +764,7 @@ public async Task GetAllTodos_ReturnsOkOfTodosResult() ## Prevent over-posting -Currently your API exposes the entire `Todo` object, including the `Secret` property you added in [The model and database context classes](#model-db-classes). In production applications, a subset of the model is often used to restrict the data that can be input and returned. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. **DTO** is used in this article. +Currently, your API exposes the entire `Todo` object, including the `Secret` property you added in [The model and database context classes](#model-db-classes). In production applications, use a subset of the model to restrict the data that clients can input and receive. Security is a major reason for this restriction. This subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. This article uses **DTO**. Use a DTO to: From 0c8de22ca4803a2c56d98dc0b0e6c789fa311e6c Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 20:05:27 -0700 Subject: [PATCH 29/40] Add VSC start instruction --- aspnetcore/tutorials/min-web-api.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index f50e153e799c..35d1c3e21101 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -1,9 +1,10 @@ --- title: "Tutorial: Create a Minimal API with ASP.NET Core" author: wadepickett -description: Learn how to build a minimal API with ASP.NET Core. +description: Create a Minimal API with ASP.NET Core using Visual Studio or Visual Studio Code. This tutorial covers GET, POST, PUT, PATCH, and DELETE endpoints for a to-do app. ai-usage: ai-assisted ms.author: wpickett +ms.reviewer: wpickett ms.date: 06/27/2026 monikerRange: '>= aspnetcore-6.0' uid: tutorials/min-web-api @@ -65,7 +66,7 @@ This tutorial creates the following API: # [Visual Studio Code](#tab/visual-studio-code) -* Open the [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal). +* Start Visual Studio Code, select **View**, and then select **Terminal** to open the [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal). * Change directories (`cd`) to the folder that contains the project folder. * Run the following commands: From 376af4e16cc5b573ef14ae5ae93cd3e5085bdb79 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 20:47:03 -0700 Subject: [PATCH 30/40] Added VSC launch config image --- aspnetcore/tutorials/min-web-api.md | 6 ++++++ .../static/10/vsc-select-luanch-2026.png | Bin 0 -> 33386 bytes 2 files changed, 6 insertions(+) create mode 100644 aspnetcore/tutorials/min-web-api/static/10/vsc-select-luanch-2026.png diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 35d1c3e21101..64204bf718a9 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -295,6 +295,12 @@ Use the POST endpoint to add data to the app. * In Visual Studio Code, press Ctrl+F5 (Windows) or control+F5 (macOS) to run the app without debugging. +* You're prompted to select a debugger. Select **C#**. + +* You're prompted to select a launch configuration. Select **C#:TodoApi [Default Configuration] TodoApi** + + ![Select a launch configuration prompt.](~/tutorials/min-web-api/static/10/vsc-select-luanch-2026.png) + The default browser launches with the following URL: `https://localhost:{PORT}` where `{PORT}` is the randomly generated port number. diff --git a/aspnetcore/tutorials/min-web-api/static/10/vsc-select-luanch-2026.png b/aspnetcore/tutorials/min-web-api/static/10/vsc-select-luanch-2026.png new file mode 100644 index 0000000000000000000000000000000000000000..a3aa9fde295169ddd1b04a44133583f69ffa32b4 GIT binary patch literal 33386 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 Date: Tue, 30 Jun 2026 20:53:53 -0700 Subject: [PATCH 31/40] Fixed VSC tab block --- aspnetcore/tutorials/min-web-api.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 64204bf718a9..f6707e7a86fb 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -208,10 +208,9 @@ In this tutorial, Scalar is used only for its API reference middleware, which re > [!NOTE] > Scalar is one of several options for an OpenAPI UI. Alternatives such as `NSwag.AspNetCore` or `Swashbuckle.AspNetCore.SwaggerUi` consume the same OpenAPI document and can be substituted for Scalar without changing the rest of the tutorial. - - --- + ## Test posting data The following code in `Program.cs` creates an HTTP POST endpoint `/todoitems` that adds data to the in-memory database: From 0ba0b447d7bb3d0dd683e8dbfb98653e1de2414c Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 21:16:31 -0700 Subject: [PATCH 32/40] Added scalar instruction line --- aspnetcore/tutorials/min-web-api.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index f6707e7a86fb..95497e9fde9d 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -127,7 +127,7 @@ Add NuGet packages to support the database used in this tutorial. --- - + ## The model and database context classes @@ -165,6 +165,8 @@ The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program. The OpenAPI lines that the template adds (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) stay in place. They now describe the Todo endpoints instead of the sample weather endpoint. +The pasted code also includes `using Scalar.AspNetCore;` and `app.MapScalarApiReference();`, which add a browser UI for testing the API. You configure the Scalar package for these lines later in this tutorial, in [Add a browser UI to view the OpenAPI document](#add-a-browser-ui-to-view-the-openapi-document). The project won't build until then. + The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container: # [Visual Studio](#tab/visual-studio) @@ -185,6 +187,8 @@ This tutorial uses [Endpoints Explorer and .http files](xref:test/http-files#use # [Visual Studio Code](#tab/visual-studio-code) + + ### Add a browser UI to view the OpenAPI document The template already generates the OpenAPI document at `/openapi/v1.json`. To explore and test the API from a browser, add a UI that consumes that document. This tutorial uses Scalar. From e6711d302b5fb704762808dd5db346cb13518b64 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 21:41:53 -0700 Subject: [PATCH 33/40] added more VSC start instruction --- aspnetcore/tutorials/min-web-api.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 95497e9fde9d..d0224c2a40ee 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -201,9 +201,9 @@ Add the [Scalar.AspNetCore](https://www.nuget.org/packages/Scalar.AspNetCore/) p dotnet add package Scalar.AspNetCore ``` -In this tutorial, Scalar is used only for its API reference middleware, which reads the OpenAPI document already generated by OpenAPI. +In this tutorial, Scalar is used only for its API reference middleware, which reads the OpenAPI document generated by the AddOpenApi and MapOpenApi calls. -* In `Program.cs`, add the `using` directive and the highlighted `MapScalarApiReference` line inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line: +Confirm that Program.cs includes the highlighted MapScalarApiReference line inside the if (app.Environment.IsDevelopment()) block, right after the app.MapOpenApi(); line, and that using Scalar.AspNetCore; is at the top of the file. You added these lines when you pasted the Todo code earlier. :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_scalar" highlight="4"::: @@ -304,12 +304,21 @@ Use the POST endpoint to add data to the app. ![Select a launch configuration prompt.](~/tutorials/min-web-api/static/10/vsc-select-luanch-2026.png) -The default browser launches with the following URL: `https://localhost:{PORT}` where `{PORT}` is the randomly generated port number. +The `TodoApi` app starts and listens on a randomly assigned local port. In the **Terminal** panel, find the `Now listening on:` line to get the URL and port, for example: +```output +info: Microsoft.Hosting.Lifetime[14] + Now listening on: http://localhost:5090 +``` + +In this example, the `TodoApi` app is listening at `http://localhost:5090`, so the port is `5090`. Your port number is likely different. -* With the app still running, in the browser, navigate to `https://localhost:{port}/scalar/v1` to display the API reference page generated by Scalar. +* To open the app in your default browser, hold Ctrl (Windows) or Cmd (macOS) and select the URL on the `Now listening on:` line in the **Terminal** panel. The browser opens at the app's root, `http://localhost:{port}`. + +* In the browser address bar, append `/scalar/v1` to the URL to display the API reference page generated by Scalar, for example `http://localhost:5090/scalar/v1`. * On the Scalar page, select the **POST /todoitems** operation, and then select **Test Request**. + * In the request body, enter JSON for a to-do item without specifying the optional `id`: ```json From be15ef8b94359e1b43db423e81ffd8317f233610 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 21:47:30 -0700 Subject: [PATCH 34/40] Add more scalar instruction --- aspnetcore/tutorials/min-web-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index d0224c2a40ee..33ce0bb835f8 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -5,7 +5,7 @@ description: Create a Minimal API with ASP.NET Core using Visual Studio or Visua ai-usage: ai-assisted ms.author: wpickett ms.reviewer: wpickett -ms.date: 06/27/2026 +ms.date: 06/28/2026 monikerRange: '>= aspnetcore-6.0' uid: tutorials/min-web-api --- From f6b846aa92b7528bcdbdad0d3dd46be753443c18 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 22:34:56 -0700 Subject: [PATCH 35/40] Added Patch instruction for resetting db with POST --- aspnetcore/tutorials/min-web-api.md | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 33ce0bb835f8..58ada9827662 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -330,7 +330,10 @@ In this example, the `TodoApi` app is listening at `http://localhost:5090`, so t * Select **Send**. -The Scalar UI displays the response, including the status code and response body. The response body shows the `id` is set to `1`. A 201 `HTTP` status code is returned, which indicates that the request was successfully processed and resulted in the creation of a new resource. +The Scalar UI displays the response, including the status code and response body. The response body shows: + +- The `id` is set to `1`. +- A 201 `HTTP` status code is returned, which indicates that the request was successfully processed and resulted in the creation of a new resource. --- @@ -344,16 +347,8 @@ Your `Program.cs` includes several GET endpoints, defined with `MapGet`: |`GET /todoitems/complete` | Get all completed to-do items | None | Array of to-do items| |`GET /todoitems/{id}` | Get an item by ID | None | To-do item| -# [Visual Studio](#tab/visual-studio) - :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_get"::: -# [Visual Studio Code](#tab/visual-studio-code) - -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_get"::: - ---- - ## Test the GET endpoints # [Visual Studio](#tab/visual-studio) @@ -482,7 +477,7 @@ This method is similar to the `MapPost` method, except it uses HTTP PUT. A succe ## Test the PUT endpoint -This sample uses an in-memory database that you must initialize each time you start the app. You need an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call. +This sample uses an in-memory database that you must initialize each time you start the app. You need an item in the database before you make a PUT call. Call POST to ensure there's an item in the database before making a PUT call. Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. @@ -515,8 +510,6 @@ Update the Todo item that has `Id = 1` and set its name to `"feed fish"`. The preceding code adds a Content-Type header and a JSON request body. * Select the **Send request** link that is above the new PUT request line. - - The PUT request is sent to the app and the response is displayed in the **Response** pane. The response body is empty, and the status code is 204. # [Visual Studio Code](#tab/visual-studio-code) @@ -540,11 +533,13 @@ Use the Scalar UI to send a PUT request: --- +The PUT request is sent to the app and the response is displayed in the **Response** pane. The response body is empty, and the status code is 204. + ## Create and examine the PATCH endpoint A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. -The next steps add a new file and modify the `Program.cs` file. Stop the app before making these changes. +The next steps add a new file and modify the `Program.cs` file. Stop the `TodoApi` app before making these changes. Leave the scalar page in the browser running. # [Visual Studio](#tab/visual-studio) @@ -558,7 +553,7 @@ The next steps add a new file and modify the `Program.cs` file. Stop the app bef The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided and a field explicitly set to a value. -This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call GET to ensure the database has an item before making a PATCH call. +This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call POST to ensure the database has an item before making a PATCH call. The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided (null) and a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool defaults to false, which could potentially overwrite an existing true value when that field isn't included in the request. @@ -598,7 +593,7 @@ This method is similar to the `MapPut` method, but it uses HTTP PATCH and only u --- -This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call GET to ensure the database has an item before making a PATCH call. +This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call POST to ensure the database has an item before making a PATCH call. Update only the `name` property of the Todo item that has `Id = 1` and set its name to `"run errands"`. @@ -636,6 +631,8 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n Use the Scalar UI to send a PATCH request: +* Refresh the scalar page in the browser so that the new `PATCH` endpoint appears. + * Select **PATCH /todoitems/{id}**, and then select **Test Request**. * Set the **id** field to `1`. From a45b334cc505273e8e818e813a7b1b1de4a0a53c Mon Sep 17 00:00:00 2001 From: wadepickett Date: Tue, 30 Jun 2026 23:11:51 -0700 Subject: [PATCH 36/40] Fixed VSC stop instructions --- aspnetcore/tutorials/min-web-api.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 58ada9827662..94b1664bc278 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -547,7 +547,7 @@ The next steps add a new file and modify the `Program.cs` file. Stop the `TodoAp # [Visual Studio Code](#tab/visual-studio-code) -* To stop the app, press Ctrl+C in the integrated terminal where the app is running. +* To stop the app, press Shift+f5. --- @@ -624,8 +624,6 @@ Update only the `name` property of the Todo item that has `Id = 1` and set its n The preceding code adds a Content-Type header and a JSON request body with only the field to update. * Select the **Send request** link that is above the new PATCH request line. - - The PATCH request is sent to the app and the response is displayed in the **Response** pane. The response body is empty, and the status code is 204. # [Visual Studio Code](#tab/visual-studio-code) @@ -649,6 +647,8 @@ Use the Scalar UI to send a PATCH request: --- +The PATCH request is sent to the app and the response is displayed in the **Response** pane. The response body is empty, and the status code is 204. + ## Examine the DELETE endpoint Your `Program.cs` file includes a single DELETE endpoint, defined with `MapDelete`: @@ -680,8 +680,6 @@ Your `Program.cs` file includes a single DELETE endpoint, defined with `MapDelet ``` * Select the **Send request** link for the DELETE request. - - The DELETE request is sent to the app and the response is displayed in the **Response** pane. The response body is empty, and the status code is 204. # [Visual Studio Code](#tab/visual-studio-code) @@ -690,13 +688,13 @@ Use the Scalar UI to send a DELETE request: * Select **DELETE /todoitems/{id}**, then **Test Request**. * Set the **id** field to `1` and select **Send**. - The DELETE request is sent to the app and the response is displayed. The response body is empty, and the status code is 204. - --- +The DELETE request is sent to the app and the response is displayed in the **Response** pane. The response body is empty, and the status code is 204. + ## Use the MapGroup API -* The next steps modify the `Program.cs` file, so stop the app before making these changes. +* The next steps modify the `Program.cs` file, so stop the app before making these changes. Leave the scalar page in the browser running. # [Visual Studio](#tab/visual-studio) @@ -704,7 +702,7 @@ Use the Scalar UI to send a DELETE request: # [Visual Studio Code](#tab/visual-studio-code) -* To stop the app, press Ctrl+C in the integrated terminal where the app is running. +* To stop the app, press Shift+f5. --- @@ -732,7 +730,7 @@ The preceding code has the following changes: ## Use the TypedResults API -The next steps modify the `Program.cs` file, so stop the app before making these changes. +The next steps modify the `Program.cs` file, so stop the app before making these changes. Leave the scalar page in the browser running. Returning rather than has several advantages, including testability and automatically returning the response type metadata for OpenAPI to describe the endpoint. For more information, see [TypedResults vs Results](/aspnet/core/fundamentals/minimal-apis/responses#typedresults-vs-results). @@ -791,7 +789,7 @@ Use a DTO to: This app needs to hide the `Secret` field, but an administrative app could choose to expose it. -* The next steps add a file, so stop the app before making these changes. +* The next steps add a file, so stop the app before making these changes. Leave the scalar page in the browser running. --- From 6f923f2837e9f8ca98e01b9ffd968e370d041221 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 1 Jul 2026 00:01:43 -0700 Subject: [PATCH 37/40] One more edit sweep. --- aspnetcore/tutorials/min-web-api.md | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 94b1664bc278..71959835b27e 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -147,7 +147,7 @@ The preceding code defines the *database context*, which is the main class that The app uses an in-memory database named `TodoList`. The database is registered later in `Program.cs` with `builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList"));`, where the string `"TodoList"` is the database name. Because the data is stored in memory, it's reset every time the app restarts. -## Replace the WeatherForecast sample with the Todo API +## Replace the `WeatherForecast` sample with the Todo API The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program.cs` and a `WeatherForecast` record at the bottom of the file. The sample is just a placeholder to show the template works - replace both with the Todo endpoints described in the following section. @@ -161,12 +161,12 @@ The `webapi` template adds a sample `GET /weatherforecast` endpoint to `Program. :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_minimal_start_all"::: +The pasted code also includes `using Scalar.AspNetCore;` and `app.MapScalarApiReference();`, which add a browser UI for testing the API. You configure the Scalar package for these lines later in this tutorial, in [Add a browser UI to view the OpenAPI document](#add-a-browser-ui-to-view-the-openapi-document). The project won't build until then. + --- The OpenAPI lines that the template adds (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) stay in place. They now describe the Todo endpoints instead of the sample weather endpoint. -The pasted code also includes `using Scalar.AspNetCore;` and `app.MapScalarApiReference();`, which add a browser UI for testing the API. You configure the Scalar package for these lines later in this tutorial, in [Add a browser UI to view the OpenAPI document](#add-a-browser-ui-to-view-the-openapi-document). The project won't build until then. - The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container: # [Visual Studio](#tab/visual-studio) @@ -332,8 +332,8 @@ In this example, the `TodoApi` app is listening at `http://localhost:5090`, so t The Scalar UI displays the response, including the status code and response body. The response body shows: -- The `id` is set to `1`. -- A 201 `HTTP` status code is returned, which indicates that the request was successfully processed and resulted in the creation of a new resource. +* The `id` is set to `1`. +* A 201 `HTTP` status code is returned, which indicates that the request was successfully processed and resulted in the creation of a new resource. --- @@ -539,7 +539,7 @@ The PUT request is sent to the app and the response is displayed in the **Respon A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. -The next steps add a new file and modify the `Program.cs` file. Stop the `TodoApi` app before making these changes. Leave the scalar page in the browser running. +The next steps add a new file and modify the `Program.cs` file. Stop the `TodoApi` app before making these changes. Leave the Scalar page in the browser running. # [Visual Studio](#tab/visual-studio) @@ -547,12 +547,10 @@ The next steps add a new file and modify the `Program.cs` file. Stop the `TodoAp # [Visual Studio Code](#tab/visual-studio-code) -* To stop the app, press Shift+f5. +* To stop the app, press Shift+F5. --- -The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided and a field explicitly set to a value. - This sample uses an in-memory database that you must initialize each time the app starts. The database must contain an item before you make a PATCH call. Call POST to ensure the database has an item before making a PATCH call. The PATCH endpoint uses a `TodoPatchDto` class with nullable properties to properly handle partial updates. By using nullable properties, the endpoint can distinguish between a field that wasn't provided (null) and a field explicitly set to a value (including false for boolean fields). Without nullable properties, a non-nullable bool defaults to false, which could potentially overwrite an existing true value when that field isn't included in the request. @@ -702,7 +700,7 @@ The DELETE request is sent to the app and the response is displayed in the **Res # [Visual Studio Code](#tab/visual-studio-code) -* To stop the app, press Shift+f5. +* To stop the app, press Shift+F5. --- @@ -750,7 +748,7 @@ The `Map` code now calls methods instead of lambdas: :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_group"::: -These following methods return objects that implement and are defined by : +The following methods return objects that implement and are defined by : :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_typed_handlers"::: @@ -791,9 +789,7 @@ This app needs to hide the `Secret` field, but an administrative app could choos * The next steps add a file, so stop the app before making these changes. Leave the scalar page in the browser running. ---- - -Create a file named `TodoItemDTO.cs` with the following code: +* Create a file named `TodoItemDTO.cs` with the following code: :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoItemDTO.cs"::: From b0b2283157b955fbe423569c63324b98d213e906 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 1 Jul 2026 15:50:48 -0700 Subject: [PATCH 38/40] Reword DI statment on code --- aspnetcore/tutorials/min-web-api.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 71959835b27e..bf1bc630cabe 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -167,7 +167,7 @@ The pasted code also includes `using Scalar.AspNetCore;` and `app.MapScalarApiRe The OpenAPI lines that the template adds (`builder.Services.AddOpenApi()` and `app.MapOpenApi()`) stay in place. They now describe the Todo endpoints instead of the sample weather endpoint. -The following highlighted code adds the database context to the [dependency injection (DI)](xref:fundamentals/dependency-injection) container: +The following highlighted code registers the app's services in the [dependency injection (DI)](xref:fundamentals/dependency-injection) container: the database context (`AddDbContext`) and the OpenAPI document generator (`AddOpenApi`): # [Visual Studio](#tab/visual-studio) @@ -203,7 +203,7 @@ Add the [Scalar.AspNetCore](https://www.nuget.org/packages/Scalar.AspNetCore/) p In this tutorial, Scalar is used only for its API reference middleware, which reads the OpenAPI document generated by the AddOpenApi and MapOpenApi calls. -Confirm that Program.cs includes the highlighted MapScalarApiReference line inside the if (app.Environment.IsDevelopment()) block, right after the app.MapOpenApi(); line, and that using Scalar.AspNetCore; is at the top of the file. You added these lines when you pasted the Todo code earlier. +Confirm that `Program.cs` includes the highlighted `MapScalarApiReference` line inside the `if (app.Environment.IsDevelopment())` block, right after the `app.MapOpenApi();` line, and that `using Scalar.AspNetCore;` is at the top of the file. You added these lines when you pasted the Todo code earlier. :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VSC_Scalar/Program.cs" id="snippet_scalar" highlight="4"::: @@ -724,7 +724,7 @@ The preceding code has the following changes: * Changes all the `app.Map` methods to `todoItems.Map`. * Removes the URL prefix `/todoitems` from the `Map` method calls. -* Run the app and test the endpoints to verify that they work the same. +* Runs the app and tests the endpoints to verify that they work the same. ## Use the TypedResults API From d812aa951a814f8d94bfccdb4567e30b5e38a017 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 1 Jul 2026 15:55:04 -0700 Subject: [PATCH 39/40] Fixed code highlight for DI. --- aspnetcore/tutorials/min-web-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index bf1bc630cabe..88b599967963 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -141,7 +141,7 @@ The `Secret` property is included to demonstrate a common real-world need: data * Create a file named `TodoDb.cs` with the following code: - :::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoDb.cs"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/TodoDb.cs"::: The preceding code defines the *database context*, which is the main class that coordinates [Entity Framework](/ef/core/) functionality for a data model. This class derives from the class. @@ -171,7 +171,7 @@ The following highlighted code registers the app's services in the [dependency i # [Visual Studio](#tab/visual-studio) -:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_DI" highlight="2"::: +:::code language="csharp" source="~/tutorials/min-web-api/samples/10.x/TodoApi_VS_EndpointExplorer/Program.cs" id="snippet_DI" highlight="2-3"::: # [Visual Studio Code](#tab/visual-studio-code) From d5a958c847e29af2eeb1c3334369ab4f7b08f798 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Thu, 9 Jul 2026 16:06:32 -0700 Subject: [PATCH 40/40] Apply suggestions from code review Co-authored-by: Tom Dykstra --- aspnetcore/tutorials/min-web-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/tutorials/min-web-api.md b/aspnetcore/tutorials/min-web-api.md index 88b599967963..6fd61b78ecf4 100644 --- a/aspnetcore/tutorials/min-web-api.md +++ b/aspnetcore/tutorials/min-web-api.md @@ -67,7 +67,7 @@ This tutorial creates the following API: # [Visual Studio Code](#tab/visual-studio-code) * Start Visual Studio Code, select **View**, and then select **Terminal** to open the [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal). -* Change directories (`cd`) to the folder that contains the project folder. +* Change directory(`cd`) to the folder that contains the project folder. * Run the following commands: ```dotnetcli @@ -537,7 +537,7 @@ The PUT request is sent to the app and the response is displayed in the **Respon ## Create and examine the PATCH endpoint -A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even to change just one. +A PATCH endpoint lets clients send only the fields they want to update, such as renaming a Todo item without resending its completion status. This approach differs from a PUT request, which replaces the entire item, so the client must send every field even if only one is changed. The next steps add a new file and modify the `Program.cs` file. Stop the `TodoApi` app before making these changes. Leave the Scalar page in the browser running.