Model binding

As discussed, model binding maps the data from HTTP requests to action method parameters. These parameters, like any other C# method, can be simple types, such as int, long, decimal, string, or the complex classes. ASP.NET Core MVC has abstracted this logic away from the developers so that they need not worry about this request data to parameter conversion. This conversion is done by the framework in a predefined order. Let's look at how the framework does this. The following is the code map diagram of the model binding subsystem:

Important things to notice in the diagram are:

  • ParameterBinder
  • ValueProvider factories
  • Value providers
  • Attributes
  • Extensions

The framework tries to bind the request data to the action parameters by name. To do so, it looks at the values for each parameter using the parameter name and the names of its public settable properties. In the preceding GetBook request URL example, the only action parameter was named id, which the framework binds to the value with the same name in the route values. The ASP.NET Core MVC framework uses three primary value providers or data sources to map HTTP request data to action parameters, in the following order:

  1. Form values (using FormValueProvider): The values in the form that came in the HTTP request body. These would generally be in HttpPost or HttpPut
  1. Route values (using RouteValueProvider): The values provided by the routing subsystem, which executes just before model binding is used
  2. Query string (using QueryStringValueProvider): The values found in the request URL query string are used

All the preceding data is stored in name value pairs in corresponding dictionaries. If, after performing this exercise, the model binding fails for some reason, it does not throw an exception; it just sets the IsValid property of ModelState to false. It's up to the action method to handle such scenarios.

Apart from the default model binding, the framework also provides a customized way to accomplish model binding by using attributes that we noted in the preceding code map diagram. We can use these attributes to alter the binding behavior of the property of a complex object, which is used as an action parameter, or to the parameter itself directly. Let's look at these attributes:

  • [BindNever]: This tells the model binder to ignore this parameter from binding
  • [BindRequired]: This attribute adds a model state error if the binding fails
  • [FromBody]: This tells the model binder to bind the data from the request body
  • [FromForm]: This tells the model binder that the value should be fetched through the form data
  • [FromHeader]: This tells the model binder that value should be fetched through a header
  • [FromQuery]: This tells the model binder that the value should be fetched through a query string
  • [FromRoute]: This tells the model binder that the value should be fetched through the route data
  • [FromServices]: This tells the model binder that dependency injection should be used to bind the parameter
  • [ModelBinder]: This attribute is used to override the default model binder, binding the source and name

The next hop of the request is validation, so let's have a look at validation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset