Some key points about model binding in ASP.NET Core

What is Model Binding

Model binding automates the process to convert HTTP request data to the action method parameters in controllers

The model binding system

  • Retrieves data from various sources such as route data, form fields, and query strings.
  • Provides the data to controllers and Razor pages in method parameters and public properties.
  • Converts string data to .NET types.
  • Updates properties of complex types.

After each property is successfully bound, model validation occurs for that property. The record of what data is bound to the model, and any binding or validation errors, is stored in ControllerBase.ModelState or PageModel.ModelState. To find out if this process was successful, the app checks the ModelState.IsValid flag.

This is how model binding explained in official documents. In this post I am sharing some key points I found interesting and hard to find when needed

Study Materials

You can learn details about model binding from official documents, and also what’s new in Asp.net core latest versions from Microsoft documents. If you are interested in custom model binding you can check here. Here is a nice post for a beginner

Key Points

Here I have added some key points from the official document that I thought requires highlighting

Targets

GET request

  • By default, properties are not bound for HTTP GET requests. 
  • If you do want properties bound to data from GET requests, set the SupportsGet property to true
[BindProperty(Name = "user_addr", SupportsGet = true)]
public string UserAddress { get; set; }

Attributes

Sources

In an HTTP request, model binding gets data in the form of key-value pairs. Sources are scanned in the following order

  1. Form fields
  2. In a controller with [ApiController] attribute gets data from the request body
  3. Route data (used only for simple types )
  4. Query string parameters (used only for simple types )
  5. Uploaded files – bound only to IFormFile or IEnumerable<IFormFile>.

Attributes

To specify the source, you can use one of the following attributes

Notes

  • When [FromBody] is applied to a complex type parameter, any binding source attributes applied to its properties are ignored
  • Don’t apply [FromBody] to more than one parameter per action method
  • If no value is sent
    • the property is set to null or a default value
    • For complex Types, model binding creates an instance by using the default constructor, without setting properties.
    • Arrays are set to Array.Empty(), except that byte[] arrays are set to null.
  • The model binder can convert source strings into simple types Enum, TimeSpan, Uri, version etc

Collections

The model binding looks for matches to parameter_name or property_name. If no match is found, it looks for one of the supported formats without the prefix.

The sequence starts at zero (0). If there are any gaps in subscript numbering, all items after the first gap are ignored.

Model Binding can use Key and Value to bind Dictionary

Globalization 

The ASP.NET Core route value provider and query string value provider:

  • Treat values as the invariant culture.
  • Expect that URLs are culture-invariant.

Input formatters

By default, JSON based input formatters added for handling JSON data. You can add other formatters for other content types

Input formatters are selected based on the Consumes attribute. If no attribute is present, it uses the Content-Type header.

Few more points

  • Model binding can also bind IFormFile, IFormFileCollection, [FormCollection] and CancellationToken
  • It is possible to use custom model binding with input formatters. To customize the model binding process when using System.Text.Json, create a class derived from JsonConverter
  • You can exclude specified types from model binding
  • [FromServices] attribute in a method parameter gets an instance of a type from the dependency injection container

Before you go

All the info in this post is mostly copied from the official document. These are some key points I have highlighted here for a quick recap when needed. Please let me know if these notes are helpful or not for you. Please leave a comment to help me improve my posts.

I would like to hear your thoughts