diff --git a/aspnetcore/fundamentals/minimal-apis.md b/aspnetcore/fundamentals/minimal-apis.md index de309cc535..d98bba96c9 100644 --- a/aspnetcore/fundamentals/minimal-apis.md +++ b/aspnetcore/fundamentals/minimal-apis.md @@ -4,7 +4,7 @@ author: rick-anderson description: Provides an overview of minimal APIs in ASP.NET Core 6.0. ms.author: riande monikerRange: '>= aspnetcore-6.0' -ms.date: 01/27/2022 +ms.date: 03/26/2022 no-loc: [".NET MAUI", "Mac Catalyst", "Blazor Hybrid", Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] uid: fundamentals/minimal-apis --- @@ -407,32 +407,31 @@ Supported binding sources: * Services provided by dependency injection * Custom -**NOTE**: Binding from forms is ***not*** natively supported in .NET 6. +> [!NOTE] +> Binding from form values is ***not*** natively supported in .NET 6. -### GET, HEAD, OPTIONS, DELETE +The following example GET route handler uses some of these parameter binding sources: -The HTTP methods `GET`, `HEAD`, `OPTIONS`, and `DELETE` don't implicitly bind from body. Bind explicitly with [`[FromBody]`](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute) or read from the request body. All other binding sources are supported. +[!code-csharp[](minimal-apis/samples/WebMinAPIs/Program.cs?name=snippet_pbg&highlight=8-11)] -**NOTE**: To support the case of `GET` with a body, directly read it from the . - - -[!code-csharp[](minimal-apis/samples/WebMinAPIs/Program.cs?name=snippet_con)] +The following table shows the relationship between the parameters used in the preceding example and the associated binding sources. | Parameter | Binding Source | -| --------- | -------------- | -| `id` | route value | -| `page` | query string | -| `service` | Provided by dependency injection | +|--|--| +| `id` | route value | +| `page` | query string | +| `customHeader` | header | +| `service` | Provided by dependency injection | -### POST, PUT, PATCH, etc +The HTTP methods `GET`, `HEAD`, `OPTIONS`, and `DELETE` don't implicitly bind from body. To bind from body (as JSON) for these HTTP methods, [bind explicitly](#explicit-parameter-binding) with [`[FromBody]`](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute) or read from the . - -[!code-csharp[](minimal-apis/samples/WebMinAPIs/Program.cs?name=snippet_ov)] +The following example POST route handler uses a binding source of body (as JSON) for the `person` parameter: -| Parameter | Binding Source | -| --------- | -------------- | -| `person` | body (as JSON) | -| `service` | Provided by dependency injection | +[!code-csharp[](minimal-apis/samples/WebMinAPIs/Program.cs?name=snippet_pbp&highlight=5)] + +The parameters in the preceding examples are all bound from request data automatically. To demonstrate the convenience that parameter binding provides, the following example route handlers show how to read request data directly from the request: + +[!code-csharp[](minimal-apis/samples/WebMinAPIs/Snippets/Program.cs?name=snippet_ManualRequestBinding&highlight=3-5,12)] ### Explicit Parameter Binding @@ -448,7 +447,8 @@ Attributes can be used to explicitly declare where parameters are bound from. | `service` | Provided by dependency injection | | `contentType` | header with the name `"Content-Type"` | -Binding from form values is ***not*** supported in .NET 6. +> [!NOTE] +> Binding from form values is ***not*** natively supported in .NET 6. ### Optional parameters diff --git a/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Program.cs b/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Program.cs index 165bef0b12..9c9e6b0ec4 100644 --- a/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Program.cs +++ b/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Program.cs @@ -1,5 +1,5 @@ #define Default // Default CREATE P1 PM PE I1 I0 IP CERT CERT2 CERT3 RE CONFIG LOG #i REB -// CONFIGB LOGB IWHB DEP R1 LE LF IM SM NR NR2 RP WILD CON OV EPB OP1 OP2 OP3 OP4 +// CONFIGB LOGB IWHB DEP R1 LE LF IM SM NR NR2 RP WILD PBG PBP EPB OP1 OP2 OP3 OP4 // CB BA CJSON MULTI STREAM XTN AUTH1 AUTH2 AUTH3 AUTH4 CORS CORS2 SWAG SWAG2 // FIL2 IHB CHNGR ADDMID #if NEVER @@ -420,8 +420,8 @@ app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}"); app.Run(); #endregion -#elif CON -#region snippet_con +#elif PBG +#region snippet_pbg var builder = WebApplication.CreateBuilder(args); // Added as service @@ -429,23 +429,21 @@ builder.Services.AddSingleton(); var app = builder.Build(); -app.MapGet("/{id}", (int id, int page, Service service) => { }); +app.MapGet("/{id}", (int id, + int page, + [FromHeader(Name = "X-CUSTOM-HEADER")] string customHeader, + Service service) => { }); class Service { } #endregion -#elif OV -#region snippet_ov +#elif PBP +#region snippet_pbp var builder = WebApplication.CreateBuilder(args); -// Added as service -builder.Services.AddSingleton(); - var app = builder.Build(); -app.MapPost("/", (Person person, Service service) => { }); - -class Service { } +app.MapPost("/", (Person person) => { }); record Person(string Name, int Age); #endregion diff --git a/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Snippets/Program.cs b/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Snippets/Program.cs new file mode 100644 index 0000000000..26f3e05f19 --- /dev/null +++ b/aspnetcore/fundamentals/minimal-apis/samples/WebMinAPIs/Snippets/Program.cs @@ -0,0 +1,27 @@ +namespace WebMinAPIs.Snippets; + +public static class Program +{ + public static void ManualRequestBinding(WebApplication app) + { + // + app.MapGet("/{id}", (HttpRequest request) => + { + var id = request.RouteValues["id"]; + var page = request.Query["page"]; + var customHeader = request.Headers["X-CUSTOM-HEADER"]; + + // ... + }); + + app.MapPost("/", async (HttpRequest request) => + { + var person = await request.ReadFromJsonAsync(); + + // ... + }); + // + } + + private record Person; +}