`[BindProperty]` tells Razor Pages to populate a public, settable `PageModel` property from incoming request data. This is model binding: ASP.NET Core converts request values into .NET values before the page handler runs. A page handler parameter is another way to receive bound data. section 16.2 section 15.3
Bind one input model
For a form that edits several fields, keep them together in one property: public class EditProductModel : PageModel { [BindProperty] public InputModel Input { get; set; } public class InputModel { public string Category { get; set; } public string Username { get; set; } } When the form is POSTed, model binding populates `Input` for `OnPost` to use. The public setters matter: without a public setter on the bound property, binding silently fails. section 16.2 section 16.4
Choose what to bind deliberately:
- By default, `[BindProperty]` does not bind on GET. Add `[BindProperty(SupportsGet = true)]` when a property needs GET binding; for a simple route value, a page handler parameter is another option. section 15.3 section 16.4
- Prefer one bound input-model property when a form has several values. Avoid `[BindProperties]` on the whole `PageModel`: binding every property can expose the page to overposting attacks. section 16.4
- Check `ModelState.IsValid` in a handler before acting on bound input. Validation runs after binding, but the handler still runs when input is invalid. section 16.1 section 16.5
Listing 16.1 Model binding requests to properties in a Razor Page
public class IndexModel: PageModel
{
[BindProperty] #1
public string Category { get; set; } #1
[BindProperty(SupportsGet = true)] #2
public string Username { get; set; } #2
public void OnGet()
{
}
public void OnPost(ProductModel model) #3
{
}
}
Compare a property bound only for non-GET requests, one that opts into GET binding, and a parameter bound directly to `OnPost`. section 16.2

