Include and Exclude Properties from Model Binding in ASP.NET Core Web API

Include and Exclude Properties from Model Binding in ASP.NET Core Web API

In this article, I will discuss How to Include and Exclude Properties from Model Binding in ASP.NET Core Web API Applications with Examples. Please read our previous article discussing How to Implement Content Negotiation in ASP.NET Core Web API Application with Examples.

How to Include and Exclude Properties from Model Binding in ASP.NET Core Web API

Let us understand how to Include and Exclude Properties from Model Binding in an ASP.NET Core Web API Application with an Example. For this demo, let us first create the following Employee Model class using which we will create a new employee as well as we can return the employees.

namespace ModelBinding.Models
{
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
    }
}
Creating the Employee Controller:

Next, create or modify the Employee Controller as follows. The GetEmployees action method is used to return all the Employees, and the AddEmployee method is used to add a new Employee.

using Microsoft.AspNetCore.Mvc;
using ModelBinding.Models;

namespace ModelBinding.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        private List<Employee> listEmployees = new List<Employee>()
        {
            new Employee(){ Id = 1, Name = "Anurag", Age = 28, Salary=1000, Gender = "Male", Department = "IT" },
            new Employee(){ Id = 2, Name = "Pranaya", Age = 28, Salary=2000, Gender = "Male", Department = "IT" },
        };

        [HttpGet]
        public ActionResult<List<Employee>> GetEmployees()
        {
            return Ok(listEmployees);
        }

        [HttpPost]
        public ActionResult<Employee> AddEmployee(Employee employee)
        {
            if(employee != null)
            {
                //Manually Setting the Id and Salary
                employee.Id = listEmployees.Count + 1;
                employee.Salary = 3000;
                listEmployees.Add(employee);
                return Ok(employee);
            }
            return BadRequest();
        }
    }
}

Now, if you run the application, then it will work as expected. If you access the api/employee endpoint using an HTTP GET Request, then you will get all the employees as shown in the below image:

How to Include and Exclude Properties from Model Binding in ASP.NET Core Web API Applications with Examples

Now, you can also make an HTTP Post request with the data in the request body, as shown in the image below, and it should work as expected.

How to Include and Exclude Properties from Model Binding in ASP.NET Core Web API Applications with Examples

How to Exclude Properties from Model Binding in ASP.NET Core Web API:

Now, what our requirement is, we don’t want to expose the ID and Salary of the Employee. That means we don’t want to return the Employee ID and Salary in the GET request. At the same time, we don’t want to accept the ID and Salary in the Post request. So, basically, we want to exclude the ID and Salary from the Model Binding.

There are several ways to achieve the same. Let me explain the same using the following two ways to exclude properties from Model Binding:

  1. Using JsonIgnore Attribute
  2. Using Custom Model Class
Using JsonIgnore Attribute:

For those properties you want to exclude from Model binding, you need to decorate them with the JsonIgnore Attribute. In our example, we need to exclude Id and Salary from Model Binding, so we need to decorate these two properties using JsonIgnore Attribute as follows:

using System.Text.Json.Serialization;
namespace ModelBinding.Models
{
    public class Employee
    {
        [JsonIgnore]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }
        [JsonIgnore]
        public int Salary { get; set; }
        public string Department { get; set; }
    }
}

With the above changes in place, run the application and access the api/employee endpoint using an HTTP GET Request, then you will get all the employees as shown in the below image without the ID and Salary properties:

How to Exclude Properties from Model Binding in ASP.NET Core Web API

Now, if you make an HTTP POST request with Id and Salary column values, then those values will be ignored by Model Binding. To prove this, run the application in debug mode and place the debugger point on the CreateEmployee action method. Let us make an HTTP POST request from Postman with the ID and Salary values as follows:

Using JsonIgnore Attribute

Now, if you verify the employee object values, then you will see it is taking the default values for Integer as 0 as shown in the below image.

Using JsonIgnore Attribute in ASP.NET Core Web API

Using Custom Model Class:

Let us assume the above Employee is the model class bound with the Entity Framework core. So, we cannot remove properties from this model. So, what we need to do is, we need to create a new model class that will map with the above Employee class.

So, let us create a class file named EmployeeDTO.cs and then copy and paste the following code. As you can see, this class has only those properties in which we want to participate in model binding. Here, we are not including the ID and Salary properties.

namespace ModelBinding.Models
{
    public class EmployeeDTO
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public int Age { get; set; }
        public string Department { get; set; }
    }
}
Modifying the Employee Controller:

Next, we need to use EmployeeDTO as the action method parameter instead of Employee. So, modify the Employee Controller as follows:

using Microsoft.AspNetCore.Mvc;
using ModelBinding.Models;

namespace ModelBinding.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        private List<Employee> listEmployees = new List<Employee>()
        {
            new Employee(){ Id = 1, Name = "Anurag", Age = 28, Salary=1000, Gender = "Male", Department = "IT" },
            new Employee(){ Id = 2, Name = "Pranaya", Age = 28, Salary=2000, Gender = "Male", Department = "IT" },
        };

        [HttpGet]
        public ActionResult<List<EmployeeDTO>> GetEmployees()
        {
            List<EmployeeDTO> employees = new List<EmployeeDTO>();

            foreach (var employee in listEmployees)
            {
                EmployeeDTO emp = new EmployeeDTO()
                {
                    //Setting the Name, Age, Gender, and Department
                    Name = employee.Name,
                    Age = employee.Age,
                    Gender = employee.Gender,
                    Department = employee.Department,
                };
                employees.Add(emp);
            }
            return Ok(employees);
        }

        [HttpPost]
        public ActionResult<EmployeeDTO> AddEmployee(EmployeeDTO employee)
        {
            if(employee != null)
            {
                Employee emp = new Employee()
                {
                    //Manually Setting the Id and Salary
                    Id = listEmployees.Count + 1,
                    Salary = 3000,

                    //Setting the Name, Age, Gender, and Department from EmployeeDTO
                    Name = employee.Name,
                    Age = employee.Age,
                    Gender = employee.Gender,
                    Department = employee.Department,
                };
                
                listEmployees.Add(emp);
                return Ok(employee);
            }
            return BadRequest();
        }
    }
}

With these changes in place, it will work as expected. Instead of manually mapping the data between the Employee and EmployeeDTO objects, you can make use of frameworks like Automapper, which we will discuss in our next article.

Why Bind and BindNever Attribute Not Working ASP.NET Core Web API?

The [Bind] and [BindNever] attributes are primarily designed for use in ASP.NET Core MVC scenarios, particularly for controlling model binding in actions that involve form submissions or query string parameters. Their primary purpose is to include or exclude model properties during the binding process. 

Why They Are Not Working as Expected in Web API?
  • Serialization-Based Binding: In ASP.NET Core Web API, model binding works differently from MVC. The data for Web API methods typically comes from the body of HTTP requests in formats like JSON or XML. ASP.NET Core deserializes this data directly into method parameters or models based on the Content-Type of the request. This process does not use the [Bind] or [BindNever] attributes because it relies on serialization frameworks (like System.Text.Json or Newtonsoft.Json) rather than the MVC model binding system.
  • Lack of Form Data: The [Bind] and [BindNever] attributes are effective when dealing with form data submissions where model binding maps form fields to model properties. In Web API, the body of a POST or PUT request is typically a serialized object, and the entire object is deserialized into the model. There’s no selective binding from form fields like in MVC applications.
Solutions and Workarounds
  • Explicit Property Control: To control what properties are updated in a Web API, you might need to implement custom logic within your action methods. For example, if certain fields should not be updated from the request, you can ignore them in your update logic or ensure they are read-only in the model.
  • Use View Models: Create specific view models that only include the properties you want to expose for binding in your API endpoints. This approach helps prevent over-posting and under-posting issues and makes your API’s data contracts explicit.
  • Use JsonIgnore Attribute: Properties decorated with JsonIgnore Attribute will be excluded from Model binding.
When Should We Include and Exclude Properties from Model Binding in ASP.NET Core Web API:

In ASP.NET Core Web API, model binding refers to the process of mapping client request data (from query strings, form data, headers, etc.) to action method parameters. Understanding when to include or exclude properties from model binding is crucial for both security and application logic integrity. Here are guidelines and practices for including and excluding properties from model binding:

When to Include Properties?
  • Required Data: Include properties that are essential for the operation of your action method. This typically includes identifiers, user inputs, and other data necessary for the completion of a request.
  • Validation Purposes: Include properties that need to be validated against certain criteria before the action method can process them. ASP.NET Core utilizes data annotations and custom validators that work with model binding to ensure data integrity.
  • Update Operations: In scenarios such as updating a resource, include only the properties that the client is allowed to update. This ensures that the API doesn’t inadvertently change properties that should remain unchanged.
When to Exclude Properties?
  • Sensitive Information: Exclude properties that contain sensitive information that should not be exposed to the client or should not be modifiable through the API, such as passwords or security tokens.
  • Read-Only Properties: Exclude properties that are read-only and not supposed to be modified by the client. This includes properties like creation dates, audit information, or any system-generated values.
  • Irrelevant Data: Exclude properties that are not relevant to the specific operation being performed by the action method. Including unnecessary data can lead to inefficient data processing and potential security risks.

In the next article, I will discuss Automapper in ASP.NET Core Web API with Examples. In this article, I try to explain How to Include and Exclude Properties from Model Binding in ASP.NET Core Web API with Examples, and I hope you enjoy this article, “How to Exclude Properties from Model Binding in ASP.NET Core Web API.”

Leave a Reply

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