ASP.NET Core
editBind route and query values
Minimal APIs bind a parameter from a route or a query string value when its type has a static TryParse method. Every ID has one, so a handler can take IDs directly:
var builder = WebApplication.CreateSlimBuilder();
builder.WebHost.UseTestServer(); // Runs the application in memory
await using var app = builder.Build();
// Route and query string values are parsed with the generated TryParse method
app.MapGet("/projects/{id}", (ProjectId id) => $"Project {id.Value}");
app.MapGet("/projects", (ProjectId? owner) => owner is { } value ? $"Projects of {value.Value}" : "All projects");
await app.StartAsync();
using var client = app.GetTestClient();
Assert.Equal("Project 42", await client.GetStringAsync(new Uri("/projects/42", UriKind.Relative)));
Assert.Equal("Projects of 7", await client.GetStringAsync(new Uri("/projects?owner=7", UriKind.Relative)));
Assert.Equal("All projects", await client.GetStringAsync(new Uri("/projects", UriKind.Relative)));
// A value that cannot be parsed is rejected
using var response = await client.GetAsync(new Uri("/projects/abc", UriKind.Relative));
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);- A route value or a query string value that does not parse, or that your validating constructor rejects, makes the request fail with
400 Bad Requestbefore the handler runs. - A nullable parameter (
ProjectId?) is optional; a non-nullable one is required. - The example runs the application in memory with
UseTestServerto check the responses; your application usesWebApplication.CreateBuilder(args)and Kestrel as usual.
Controllers bind route and query string values to IDs too: MVC model binding converts simple types with their TypeConverter, which the generator provides.
Read and write JSON bodies
Request and response bodies use System.Text.Json, which uses the generated converter: an ID in a body is its value. A Native AOT application serializes with a source-generated JsonSerializerContext, which ignores the converter. See Source generation and Native AOT.