Model Binding using FromQuery in ASP.NET Core Web API

Model Binding using FromQuery in ASP.NET Core Web API

In this article, I will discuss How to Implement Model Binding Using FromQuery in ASP.NET Core Web API Application with Examples. Please read our previous article discussing Model Binding Using FromForm in ASP.NET Core Web API with Examples.

What is a Query String in ASP.NET Core Web API?

A Query String in ASP.NET Core Web API is a part of the URL that comes after the question mark (?) and is used to pass key-value pairs of information to the server. This method of sending data to the server is part of the HTTP request and is typically used for filtering, sorting, or specifying the nature of the request without changing the resource’s URI.

A Query String comprises one or more key-value pairs, where each pair is separated by an ampersand (&). The key and value in each pair are separated by an equals sign (=). For example, in the URL https://example.com/api/values?Department=IT&Gender=Male, the query string is Department=IT&Gender=Male, with Department and Gender being the keys and IT and Male their respective values.

Model Binding using FromQuery in ASP.NET Core Web API

Model binding in ASP.NET Core Web API allows you to map request data to action method parameters automatically. The FromQuery attribute is one of the model binding sources that tells ASP.NET Core to get the value of a method parameter from the query string of the request URL.

This is particularly useful for HTTP GET requests, where you want to retrieve data based on parameters supplied as part of the query string, such as filtering data, pagination, or passing other simple parameters to the server without needing a complex request body.

When a client sends a request to your Web API, the query string values can be automatically bound to the parameters of the corresponding action method, provided the names of the query string parameters match the names of the action method’s parameters. The following are the key points of the FromQuery attribute:

  • Purpose: FromQuery specifies that an action method parameter should be bound from the query string.
  • Usage Scenario: Ideal for reading complex data from the query string in HTTP GET requests.
  • How It Works: ASP.NET Core model binding system automatically maps query parameters from the URL to the parameters in your controller action method marked with [FromQuery].
Example to Understand FromQuery Attribute in ASP.NET Core Web API:

Let us see an Example to Understand the FromQuery Attribute in ASP.NET Core Web API. First, modify the UserModel class as follows, which will hold the User data.

namespace ModelBinding.Models
{
    public class UserModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Department { get; set; }
        public string Gender { get; set; }
        public int Salary { get; set; }
    }
}
Basic Usage:

To use FromQuery, you need to decorate the parameters of your action method with the [FromQuery] attribute. This tells ASP.NET Core to look for values with matching names in the query string and bind them to the parameters. For a better understanding, please modify the User Controller as follows.

using Microsoft.AspNetCore.Mvc;
using ModelBinding.Models;
namespace ModelBinding.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private static List<UserModel> Users = new List<UserModel>
        {
            new UserModel { Id = 1, Name = "Rakesh", Department = "IT", Gender = "Male", Salary = 1000 },
            new UserModel { Id = 2, Name = "Priyanka", Department = "IT", Gender = "Female", Salary = 2000  },
            new UserModel { Id = 3, Name = "Suresh", Department = "HR", Gender = "Male", Salary = 3000 },
            new UserModel { Id = 4, Name = "Hina", Department = "HR", Gender = "Female", Salary = 4000 },
            new UserModel { Id = 5, Name = "Pranaya", Department = "HR", Gender = "Male", Salary = 35000 },
            new UserModel { Id = 6, Name = "Pooja", Department = "IT", Gender = "Female", Salary = 2500 },
        };

        [HttpGet]
        public IActionResult GetProducts([FromQuery] string Department)
        {
            // Implementation to retrieve employees based on the Department
            var FilteredUsers = Users.Where(emp => emp.Department.Equals(Department, StringComparison.OrdinalIgnoreCase)).ToList();
            if(FilteredUsers.Count > 0)
            {
                return Ok(FilteredUsers);
            }
            return NotFound($"No Users Found with Department: {Department}");
        }
    }
}

As you can see in the above code, we have marked the Department parameter with the FromQuery attribute, which means the ASP.NET Core Framework will now map this parameter with the query string parameter named Department. Now, run the application and try to access the above endpoint using the Department query string as shown in the below image:

Example to Understand FromQuery Attribute in ASP.NET Core Web API

Customizing Query Parameter Names:

You can customize the query parameter names by specifying the name in the [FromQuery] attribute if the query string parameter name should be different from the method parameter name. For a better understanding, please modify the User Controller as follows:

using Microsoft.AspNetCore.Mvc;
using ModelBinding.Models;
namespace ModelBinding.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private static List<UserModel> Users = new List<UserModel>
        {
            new UserModel { Id = 1, Name = "Rakesh", Department = "IT", Gender = "Male", Salary = 1000 },
            new UserModel { Id = 2, Name = "Priyanka", Department = "IT", Gender = "Female", Salary = 2000  },
            new UserModel { Id = 3, Name = "Suresh", Department = "HR", Gender = "Male", Salary = 3000 },
            new UserModel { Id = 4, Name = "Hina", Department = "HR", Gender = "Female", Salary = 4000 },
            new UserModel { Id = 5, Name = "Pranaya", Department = "HR", Gender = "Male", Salary = 35000 },
            new UserModel { Id = 6, Name = "Pooja", Department = "IT", Gender = "Female", Salary = 2500 },
        };

        [HttpGet]
        public IActionResult GetProducts([FromQuery(Name ="Dept")] string Department)
        {
            // Implementation to retrieve employees based on the Department
            var FilteredUsers = Users.Where(emp => emp.Department.Equals(Department, StringComparison.OrdinalIgnoreCase)).ToList();
            if (FilteredUsers.Count > 0)
            {
                return Ok(FilteredUsers);
            }
            return NotFound($"No Users Found with Department: {Department}");
        }
    }
}

With the above changes in place, you need to use the query string name Dept instead of Department, as shown in the image below.

Model Binding Using FromQuery in ASP.NET Core Web API

FromQuery with Complex Type in ASP.NET Core Web API:

If you have multiple query parameters, it might be cleaner to use a complex type to represent them. ASP.NET Core can bind query string parameters to properties of a complex type.

The FromQuery Attribute can also bind complex types. By default, the ASP.NET Core map the complex type parameter with the request body. But if you want, then you can also map the complex type parameter with the query string. For this, we need to decorate the complex type parameter with the FromQuery Attribute, and the query string keys must match the Complex type properties.

Let us understand this with an example. Suppose we want to search the users by Department and Gender. So, let us first create a class file named UserSearch.cs and then copy and paste the following code. We will use this model to map with the query string parameters.

namespace ModelBinding.Models
{
    public class UserSearch
    {
        public string Department { get; set; }
        public string Gender { get; set; }
    }
}
Modifying the User Controller:

Next, modify the User Controller as follows. Here, we have marked the UserSearch parameter with the FromQuery Attribute, meaning this parameter’s properties will map with the query string parameter.

using Microsoft.AspNetCore.Mvc;
using ModelBinding.Models;
namespace ModelBinding.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private static List<UserModel> Users = new List<UserModel>
        {
            new UserModel { Id = 1, Name = "Rakesh", Department = "IT", Gender = "Male", Salary = 1000 },
            new UserModel { Id = 2, Name = "Priyanka", Department = "IT", Gender = "Female", Salary = 2000  },
            new UserModel { Id = 3, Name = "Suresh", Department = "HR", Gender = "Male", Salary = 3000 },
            new UserModel { Id = 4, Name = "Hina", Department = "HR", Gender = "Female", Salary = 4000 },
            new UserModel { Id = 5, Name = "Pranaya", Department = "HR", Gender = "Male", Salary = 35000 },
            new UserModel { Id = 6, Name = "Pooja", Department = "IT", Gender = "Female", Salary = 2500 },
        };

        [HttpGet]
        public IActionResult GetUsers([FromQuery] UserSearch userSearch)
        {
            var FilteredUsers = new List<UserModel>();
            if (userSearch != null)
            {
                FilteredUsers = Users.Where(
                       emp => emp.Department.Equals(userSearch.Department, StringComparison.OrdinalIgnoreCase) ||
                       emp.Gender.Equals(userSearch.Gender, StringComparison.OrdinalIgnoreCase)
                       ).ToList();

                if (FilteredUsers.Count > 0)
                {
                    return Ok(FilteredUsers);
                }
                return NotFound($"No Users Found with Department: {userSearch?.Department} and Gender: {userSearch?.Gender}");
            }
            return BadRequest("Invalid Search Criteria");
        }
    }
}

With the above changes in place, run the application and access the above endpoint with the Department and Gender Query string, such as Department=HR&Gender=Male. It should work as expected, as shown in the image below. For a query string Department=HR&Gender=Male, ASP.NET Core will create an instance of UserSearch with Department set to “HR” and Gender set to Male.

FromQuery with Complex Type in ASP.NET Core Web API

In the above example, both Department and Gender query string parameters are mandatory. For example, if you only pass the Department query string, then you will get the following error:

FromQuery Attribute with Complex Type in ASP.NET Core Web API

This is because, in our UserSearch model class, we have not made the Gender and Department nullable type. We have also decorated our User Controller with the ApiController attribute. The ApiController will consider all non-nullable types as mandatory fields, and if no value is supplied for those parameters, then it will return 400 Bad Requests, and that is what you see in the previous request.

How to Make the Query String Parameters Optional in ASP.NET Core Web API?

If you want to make the Query string parameters optional, then you need to make the action method parameters optional. So, what we need to do is, we need to make the Gender and Department parameters nullable type. So, modify the UserSearch class as follows:

namespace ModelBinding.Models
{
    public class UserSearch
    {
        public string? Department { get; set; }
        public string? Gender { get; set; }
    }
}

With the above changes, run the application and access the endpoint, and you should get the result as expected, as shown in the below image:

How to Make the Query String Parameters Optional in ASP.NET Core Web API?

How Does FromQuery Work in ASP.NET Core Web API?

When a request is made to an ASP.NET Core Web API, the model binding system checks the parameters of the action method being called. If a parameter is decorated with the FromQuery attribute, the model binder looks for a value with a matching name in the query string of the request URL.

  • Parameter Binding: If the method parameter is a simple type (e.g., int, string, DateTime), model binding looks for a query string parameter with the same name and attempts to convert the value to the parameter type.
  • Complex Type Binding: For complex types, model binding attempts to map query string parameters to the properties of the complex type. Each property is matched based on the name. For example, if you have a complex object with properties FirstName and LastName, you can pass them in the query string as ?FirstName=John&LastName=Doe.
When to Use FromQuery Model Binding in ASP.NET Core Web API?

Here are scenarios and considerations for using FromQuery model binding:

  • Retrieving Simple Data from the Query String: Use FromQuery to retrieve simple or primitive data types directly from the query string. This is common in GET requests where you need to filter, sort, or paginate data. For example, fetching a list of products filtered by a category or price range.
  • Complex Types from the Query String: Although less common, FromQuery can also bind complex types from the query string if the data can be represented as a series of key-value pairs. This requires the query string to be structured correctly, with keys matching the property names of the complex type.
  • Readability and RESTful API Design: FromQuery is preferred when designing RESTful APIs that require readable and easily constructed URLs. Query strings are ideal for optional parameters or when the number of parameters is variable, enhancing the flexibility and usability of your API.
  • Non-Body Data Sources: In HTTP methods like GET, where the body is not typically used to send data, FromQuery is particularly useful. Using the query string to pass parameters adheres to the constraints of such HTTP methods.
  • Combining With Other Binding Sources: FromQuery can be used alongside other model binding attributes (such as FromRoute, FromBody, and FromHeader) in the same action method to bind parameters from different parts of the HTTP request. This allows for flexible and precise data retrieval strategies.

In the next article, I will discuss Model Binding Using FromRoute in ASP.NET Core Web API with Examples. In this article, I try to explain Model Binding Using FromQuery in ASP.NET Core Web API with Examples. I hope you enjoy this article “Model Binding Using FromQuery in ASP.NET Core Web API”.

Leave a Reply

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