liveBook · Manning

Model binding

As explained in Pro ASP.NET Core 7, Tenth Edition

A model binder is an ASP.NET Core component that converts request data into objects or values supplied to application handlers.

Model binding turns HTTP request values into .NET values and objects before an ASP.NET Core controller action or Razor Page handler runs. Declare a parameter—or, in a Razor Page, a bindable property—and work with C# data instead of parsing the request yourself. section 28.0 section 3.2.6

The shape of the target determines how values are assembled:

  • A simple parameter takes one request value, converted to a type such as decimal, bool, or a date. section 28.3
  • A complex parameter gets a new object whose public properties are bound individually. Nested objects use dotted names such as Category.Name; input tag helpers can generate those names with asp-for. section 28.4 section 28.4.2
  • Repeated input names can populate an array. Indexed names such as Data[0] specify positions; sequence collections can also be binding targets. section 28.5.1 section 28.5.2

By default, binders search form data, the request body for controllers decorated with ApiController, route variables, then query strings, stopping when they find a suitable value. If a route supplies id, a competing query-string id does not win. Source attributes can direct binding to a particular part of the request. section 28.2 section 28.0

Binding is best effort, not a guarantee that the request supplied everything. A missing long argument can become 0; an unfilled complex-object property keeps its type’s default. Handle those cases with parameter defaults, nullable types, or code that tolerates missing data. Otherwise, the failure may surface later—for example, in a database query rather than in the binder. section 28.3.2 section 28.4

In Razor Pages, [BindProperty] binds a page-model property without duplicating it as a handler parameter. Its property name participates in matching form fields; GET binding requires SupportsGet = true. When binding handler parameters instead, check the generated input names: asp-for="Product.Name" produces Product.Name, not the name expected by a parameter called name. section 28.4.1 section 28.3.1

Validate a submitted RSVP

A [HttpPost] RsvpForm(GuestResponse guestResponse) action receives an object populated from form fields. Put [Required] and [EmailAddress] attributes on its properties, then check ModelState.IsValid: store the response and render a Thanks view when valid, or return the form when invalid. Make an unanswered attendance choice a nullable bool so [Required] can distinguish it from false. section 3.2.6 section 3.2.9

Do not treat an omitted form field as protection for a sensitive property: a client can submit its own value. Limit accepted properties with [Bind] or [BindNever], or receive data in a separate binding-target class containing only permitted fields. The latter prevents an unwanted ProductId from being copied into a new database entity. section 28.4.3 section 19.5.2

Listing 19.16 The ProductBindingTarget.cs file in the WebApp/Models folder
namespace WebApp.Models {
   public class ProductBindingTarget {
       
       public required string Name { get; set; }
               
       public decimal Price { get; set; }
               
       public long CategoryId { get; set; }
               
       public long SupplierId { get; set; }
               
       public Product ToProduct() => new Product() {
           Name = this.Name, Price = this.Price,
           CategoryId = this.CategoryId, SupplierId = this.SupplierId
       };
   }
}

The binding target accepts only the fields needed to create a product, then explicitly copies them into the application’s Product object. section 19.5.2

How Pro ASP.NET Core 7, Tenth Edition covers it

How deep it goes
Works through source order, simple and nested types, collections, defaults, property selection, and over-binding; manual binding is listed but not demonstrated here.
Examples
Uses an RSVP form, a product form with nested fields, collection inputs, and a product API binding target.
What it assumes
Assumes familiarity with C# types and HTTP forms while explaining how ASP.NET Core supplies action and handler values.
What you can do after
Build it from scratch by declaring binding targets, matching input names, handling missing values, and restricting client-settable properties.
How it connects
Links HTTP routing, Razor Pages, tag helpers, validation, and over-binding to request-to-object conversion.

Also explained in

Compare how 3 books explain model binding →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Pro ASP.NET Core 7, Tenth Edition. The section links point to the parts of the book it draws on.