Show examples of "manual" parameter binding (#25142)

pull/25436/head
Kirk Larkin 2022-03-26 08:05:25 +00:00 committed by GitHub
parent e7fa751de6
commit 5daa6a9409
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 32 deletions

View File

@ -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 <xref:Microsoft.AspNetCore.Http.HttpRequest>.
<!-- TODO - finish Service so app displays id and page -->
[!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 <xref:Microsoft.AspNetCore.Http.HttpRequest>.
<!-- TODO - finish Service so post works with person -->
[!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

View File

@ -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<Service>();
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<Service>();
var app = builder.Build();
app.MapPost("/", (Person person, Service service) => { });
class Service { }
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
#endregion

View File

@ -0,0 +1,27 @@
namespace WebMinAPIs.Snippets;
public static class Program
{
public static void ManualRequestBinding(WebApplication app)
{
// <snippet_ManualRequestBinding>
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<Person>();
// ...
});
// </snippet_ManualRequestBinding>
}
private record Person;
}