diff --git a/aspnetcore/mvc/models/model-binding.md b/aspnetcore/mvc/models/model-binding.md index 3f87461d22..35ed93ffb9 100644 --- a/aspnetcore/mvc/models/model-binding.md +++ b/aspnetcore/mvc/models/model-binding.md @@ -379,8 +379,41 @@ For `Dictionary` targets, model binding looks for matches to *parameter_name* or * selectedCourses["1050"]="Chemistry" * selectedCourses["2000"]="Economics" - +::: moniker range="> aspnetcore-5.0" +## Constructor binding and record types + +Model binding requires that complex types have a parameterless constructor. Both `System.Text.Json` and `Newtonsoft.Json` based input formatters support deserialization of classes that do not have a parameterless constructor. + +C# 9 introduces record types which are a great way to succintly represent data over the network. ASP.NET Core adds support for model binding and validating record types with a single constructor. + +```C# +public record Person([Required] string Name, [Range(0, 150)] int Age); + +public class PersonController +{ + public IActionResult Index() => View(); + + [HttpPost] + public IActionResult Index(Person person) + { + // ... + } +} + +// Person/Index.cshtml +@model Person + +Name: +... +Age: +``` + +When validating record types, the runtime looks for validation metadata specifically on parameters rather than on properties. + +::: moniker-end + + ## Globalization behavior of model binding route data and query strings The ASP.NET Core route value provider and query string value provider: