Model Binding in ASP.NET Core MVC

Model Binding in ASP.NET Core MVC

In this article, I will discuss Model Binding in ASP.NET Core MVC Applications with Examples. Please read our previous article discussing Tag Helpers in ASP.NET Core MVC. At the end of this article, you will understand the following pointers:

  1. What is Model Binding in ASP.NET Core?
  2. Example Without Using Model Binding in ASP.NET Core MVC
  3. What is FormCollection in ASP.NET Core MVC?
  4. Example Using Model Binding in ASP.NET Core MVC
  5. How Does Model Binding Work in ASP.NET Core?
  6. Different Model Binding Techniques in ASP.NET Core MVC
  7. Why Model Binding in ASP.NET Core?
  8. Default Model Binders and Their Orders in ASP.NET Core MVC.
What is Model Binding in ASP.NET Core?

Model Binding is a mechanism in the ASP.NET Core Application that extracts the data from an HTTP request and provides them to the controller action method parameters or object properties. The action method parameters can be simple types like integers, strings, etc., or complex types such as Student, Order, Product, etc.

In ASP.NET Core MVC, Model Binding abstracts the complexities of dealing with raw HTTP request data. That means we don’t need to think about how the data from different sources, such as posted forms query strings, headers, route data, and JSON request bodies, are mapped to action method parameters.

Example Without Using Model Binding in ASP.NET Core MVC

Let us first understand one example without using Model Binding, i.e., how to capture request data in an ASP.NET Core MVC Application without Model Binding. In ASP.NET Core MVC, FormCollection is a method for extracting data manually from HTTP requests. Let us proceed and understand how to use FormCollection to fetch the data from HTTP Requests.

First, create a new ASP.NET Core MVC Application named ModelBindingDemo. Then, modify the HomeController as follows. As you can see, we are using FormCollection as a parameter to capture the form data using the controller action method.

using Microsoft.AspNetCore.Mvc;
namespace ModelBindingDemo.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public string SubmitForm(IFormCollection form)
        {
            var UserName = form["UserName"].ToString();
            var UserEmail = form["UserEmail"].ToString();

            // Handle data as needed...
            return $"User Created: UserName: {UserName}, UserEmail: {UserEmail}";
        }
    }
}
Understanding SubmitForm Action Method:
  • The SubmitForm Action Method is decorated with the [HttpPost] Attribute. [HttpPost] is an attribute that specifies that this action method should only handle POST requests. POST requests are generally used to send data from the client to the server, such as when submitting a form.
  • SubmitForm(IFormCollection form) method handles the Form Submission. It takes an IFormCollection parameter named form, representing the form data sent in the HTTP request.
  • var UserName = form[“UserName”].ToString(); and var UserEmail = form[“UserEmail”].ToString(); extract the values for UserName and UserEmail from the submitted form data. The keys “UserName” and “UserEmail” correspond to the names of form inputs on the client-side form.
  • The method concludes by returning a string that confirms the received data, including the username and email address. In a real application, you would typically handle the form data by saving it to a database or performing other business logic instead of just returning it as a string.

Next, modify the Index.cshtml view as follows:

@{
    ViewData["Title"] = "Home Page";
}

<form method="post" asp-controller="Home" asp-action="SubmitForm">
    <label>Name:</label>
    <input type="text" name="UserName" />
    <br />

    <label>Email:</label>
    <input type="text" name="UserEmail" />
    <br />

    <button type="submit">Submit</button>
</form>
What is FormCollection in ASP.NET Core MVC?

In ASP.NET Core MVC, FormCollection is a class used to hold the data submitted from an HTML form. Essentially, it provides a way to access form values sent via HTTP POST or PUT requests. This class is part of the Microsoft.AspNetCore.Http namespace. It acts as a collection of key-value pairs, where each key is a string representing the form field name, and the value is a StringValues type representing the form field’s data. The following are the limitations of FormCollection in ASP.NET Core MVC:

  • Less Type Safety: Errors related to type mismatches or missing fields might only be detected at runtime.
  • No Model Validation: We need to handle validation and error messages manually.
  • Security: Directly accessing form values using FormCollection can cause security issues like SQL injection or XSS attacks.
Using Model Binding in ASP.NET Core MVC

Let’s see how we can rewrite the previous example using Model binding. First, let’s create a model to hold the UserName and UserEmail. So, create a class file with the name User.cs within the Models folder and copy and paste the following code.

using System.ComponentModel.DataAnnotations;
namespace ModelBindingDemo.Models
{
    public class User
    {
        [Required]
        public string UserName { get; set; }
        [Required]
        public string UserEmail { get; set; }
    }
}

Next, modify the Index.cshtml view as follows. As you can see, the User is now the model for the following view.

@model User
@{
    ViewData["Title"] = "Home Page";
}

<form method="post" asp-controller="Home" asp-action="SubmitForm">
    <label>Name:</label>
    <input asp-for="UserName" />
    <br />

    <label>Email:</label>
    <input asp-for="UserEmail" />
    <br />

    <button type="submit">Submit</button>
</form>

Next, modify the HomeController as follows:

using Microsoft.AspNetCore.Mvc;
using ModelBindingDemo.Models;

namespace ModelBindingDemo.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public string SubmitForm(User user)
        {
            if (user != null)
            {
                if (ModelState.IsValid)
                {
                    // Handle data as needed...
                    return $"User Created: UserName: {user.UserName}, UserEmail: {user.UserEmail}";
                }
            }
            return "Some Error Occured";
        }
    }
}

Now, run the application, and it should work as expected. Let’s proceed to understand Model Binding in detail.

What is Model Binding in ASP.NET Core MVC?

Model binding in ASP.NET Core MVC is a mechanism where HTTP request data (such as form values, route data, query string parameters, request body, and HTTP headers) is automatically parsed and assigned to the parameters of an action method in a controller.

This allows us to work directly with strongly typed .NET objects in our action methods. This will eliminate the need to manually parse and convert the raw HTTP request data to .NET objects in the ASP.NET Core MVC Application. It also means that we don’t have to manually extract data from the request; the framework handles it for us based on the parameters of our action methods.

How Does Model Binding Work in ASP.NET Core?

When a request is made to an MVC controller, the model binding system:

  • Retrieves Data: It looks at the source of the incoming HTTP request (like form values, route data, query string parameters, request body, and HTTP headers).
  • Converts Data: It then attempts to convert these data values into .NET types that match the parameters of the controller action being called.
  • Validation: Optionally, model binding also works with data annotation attributes to validate data as it’s converted into types.

Note: The model binder looks for data in the request that matches the names of the action method’s parameters. Depending on the source attribute (e.g., [FromQuery], [FromBody], [FromRoute]), it knows where to look, such as in the query string, the request body, or the route data. 

Different Model Binding Techniques in ASP.NET Core MVC:

You can configure model binding using various attributes that control how data is extracted from the request. Some common attributes include:

  • [FromBody]: To bind data from the request body.
  • [FromForm]: To bind data from form fields.
  • [FromQuery]: To bind data from the query string.
  • [FromRoute]: To bind data from route data.
  • [FromHeader]: To bind data from headers.

Note: We will discuss all these model-binding techniques in detail in our next article. This article will help us understand the basics of these model binding techniques and how we can use them in our controller action methods.

FromBody:

This attribute tells ASP.NET Core to bind data from the request body to the parameter of an action method. It’s commonly used when complex types like objects or collections, typically in JSON or XML format, are expected in the body of a POST request. It is commonly used in Restful Services.

[HttpPost]
public IActionResult Create([FromBody] Product product) 
{ 
    //... 
}
FromForm:

The [FromForm] attribute binds data from HTML form fields to action method parameters. It’s suitable for handling form submissions via HTTP POST requests and is commonly used in ASP.NET Core MVC Applications.

[HttpPost]
public IActionResult Register([FromForm] UserRegistrationModel user) 
{ 
    //... 
}
FromQuery:

The [FromQuery] attribute binds data from the URL’s query string to action method parameters. It’s often used for GET requests where data is passed in the URL.

public IActionResult Search([FromQuery] string query) 
{ 
    //... 
}
FromRoute:

The [FromRoute] attribute is used to bind data from route parameters to action method parameters. Route parameters are placeholders in the URL defined in your route templates.

[HttpGet("{id}")]
public IActionResult Get([FromRoute]int id) 
{ 
    //... 
}
FromHeader:

The [FromHeader] attribute binds data from HTTP headers to action method parameters. It’s useful for extracting custom headers or standard headers like Authorization, User-Agent, etc.

public IActionResult CheckUserAgent([FromHeader(Name = "User-Agent")] string userAgent) 
{ 
    //... 
}
Why Model Binding in ASP.NET Core?

There are several reasons why model binding is important. They are as follows:

  • Automatic Mapping: Model binding automatically maps data from HTTP requests to action method parameters. Each parameter’s data source might include the request body, query string, headers, cookies, or route data.
  • Support for Complex Types: It supports binding simple types like integers and strings, as well as complex types like custom classes and collections. For complex types, model binding looks for matching keys in the incoming data and assigns values to properties or fields in the object.
  • Customization and Extensibility: Developers can customize the binding process by using attributes like [FromBody], [FromQuery], [FromRoute], [FromHeader], [FromForm], and [FromServices]. These attributes specify the source of the data for a particular action method parameter.
  • Validation: Model binding works closely with model validation. Once data is bound to parameters, it can be validated using data annotations and custom validation rules. Invalid model states can be handled within the action methods.

Built-in Model Binders in ASP.NET Core MVC:

In ASP.NET Core MVC, model binding involves a sequence of providers, each designed to handle different types of input data. The built-in model binders are integrated into the framework and configured to work in a specific sequence that is generally suitable for most use cases.

The default order of these providers is designed to handle most typical scenarios effectively. This order determines how the framework attempts to bind incoming data to action method parameters or properties of complex types. To see the same, please add the following code to the Program.cs class file. It will display the default order of all the registered Model Binders in the ASP.NET Core Application. Once you run the application, check the Console Window.

builder.Services.AddControllersWithViews(options =>
{
    foreach (var provider in options.ModelBinderProviders)
    {
        Console.WriteLine(provider.GetType().ToString());
    }
});

If you want to control the “priority” or decide which source to use, then you need to specify the appropriate attribute explicitly on each action method parameter. For example, if you have an action method that could receive a userId either from the query string or as a JSON payload, then you can decorate the parameter using either [FromQuery] or [FromBody] as follows:

public IActionResult GetUser([FromQuery] int userId)
{
    // Uses userId from the query string
}

// OR

public IActionResult UpdateUser([FromBody] User user)
{
    // User object is expected as a JSON body which includes userId
}

In the next article, I will discuss Using FromForm to Perform Model Binding in ASP.NET Core MVC with Examples. In this article, I try to explain the basic concepts of Model Binding. I hope you enjoy this article on Model Binding in ASP.NET Core MVC.

9 thoughts on “Model Binding in ASP.NET Core MVC”

  1. blank
    Mahinur Rahaman Hridoy

    Don’t we have the opportunity to learn a little more?
    I’m from Bangladesh.
    Thanks a lot.. This is the best tutorial site for me. I have never seen such a website

  2. blank

    Its a greattt tutorial …but so many things also we are expecting ..Please provide the continuation of this technology

Leave a Reply

Your email address will not be published. Required fields are marked *