Parameter Binding in ASP.NET Web API

In the previous section, we learned how Web API route an HTTP request to a controller and action method. Here, we will learn how Web API binds HTTP request data to the parameters of an action method.

Action methods in Web API controllers can have one or more parameters of different types. It can be either primitive type or complex type. Web API binds action method parameters with the URL's query string or with the request body depending on the parameter type.

By default, if the parameter type is of .NET primitive types such as int, bool, double, string, GUID, DateTime, decimal, or any other type that can be converted from string type, then it sets the value of a parameter from the query string. And if the parameter type is the complex type, then Web API tries to get the value from the request body by default.

The following table lists the default rules for parameter binding.

HTTP Method Query String Request Body
GET Primitive Type,
Complex Type
NA
POST Primitive Type Complex Type
PUT Primitive Type Complex Type
PATCH Primitive Type Complex Type
DELETE Primitive Type,
Complex Type
NA

Let's see how Web API get values of action method parameters from the HTTP request.

Get Action Method with Primitive Parameter

Consider the following example of the GET action method that includes a single primitive type parameter.

Example: Primitive Parameter Binding
public class StudentController : ApiController
{
    public Student Get(int id) 
    {
              
    }
}

As you can see, the above HTTP GET action method includes the id parameter of the int type. So, Web API will try to extract the value of id from the query string of the requested URL, convert it into int and assign it to the id parameter of the GET action method. For example, if an HTTP request is http://localhost/api/student?id=1 then the value of the id parameter will be 1.

The followings are valid HTTP GET Requests for the above action method.

http://localhost/api/student?id=1

http://localhost/api/student?ID=1

Note:
Query string parameter name and action method parameter name must be the same (case-insensitive). If names do not match, then the values of the parameters will not be set. The order of the parameters can be different.

Multiple Primitive Parameters

Consider the following example of the GET action method with multiple primitive parameters.

Example: Multiple Parameters Binding
public class StudentController : ApiController
{
    public Student Get(int id, string name) 
    {

    }
}

As you can see above, an HTTP GET method includes multiple primitive type parameters. So, Web API will try to extract the values from the query string of the requested URL. For example, if an HTTP request is http://localhost/api/student?id=1&name=steve, then the value of the id parameter will be 1, and the name parameter will be "steve".

Followings are valid HTTP GET Requests for the above action method.

http://localhost/api/student?id=1&name=steve

http://localhost/api/student?ID=1&NAME=steve

http://localhost/api/student?name=steve&id=1

Note:
Query string parameter names must match with the name of an action method parameter. However, they can be in a different order.

POST Action Method with Primitive Parameter

An HTTP POST request is used to create a new resource. It can include request data into the HTTP request body and also in the query string.

Consider the following Post action method.

Example: Post Method with Primitive Parameter
public class StudentController : ApiController
{
    public Student Post(id id, string name)
    {
           
    }
}

As you can see above, the Post() action method includes primitive type parameters id and name. So, by default, Web API will get values from the query string. For example, if an HTTP POST request is http://localhost/api/student?id=1&name=steve, then the value of the id parameter will be 1 and the name parameter will be "steve" in the above Post() method.

Now, consider the following Post() method with the complex type parameter.

Example: Post Method with Complex Type Parameter
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class StudentController : ApiController
{
    public Student Post(Student stud)
    {
           
    }
}

The above Post() method includes the Student type parameter. So, as a default rule, Web API will try to get the values of the stud parameter from the HTTP request body.

Following is a valid HTTP POST request in the fiddler for the above action method.

Parameter Binding

Web API will extract the JSON object from the HTTP request body above, and convert it into a Student object automatically because the names of JSON object's properties match with the name of the Student class properties (case-insensitive).

ADVERTISEMENT

POST Method with Mixed Parameters

The HTTP Post action methods can include primitive and complex type parameters. Consider the following example.

Example: Post Method with Primitive and Complex Type Parameters
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class StudentController : ApiController
{
    public Student Post(int age, Student student)
    {

    }
}

The above Post method includes both primitive and complex type parameters. So, by default , Web API will get the age parameter from query string and student parameter from the request body.

Following is a valid HTTP POST request in the fiddler for the above action method.

Parameter Binding
Note:
Post action method cannot include multiple complex type parameters because, at most, one parameter is allowed to be read from the request body.

Parameter binding for Put and Patch method will be the same as the POST method in Web API.

[FromUri] and [FromBody]

You have seen that by default, ASP.NET Web API gets the value of a primitive parameter from the query string and a complex type parameter from the request body. But, what if we want to change this default behavior?

Use [FromUri] attribute to force Web API to get the value of complex type from the query string and [FromBody] attribute to get the value of primitive type from the request body, opposite to the default rules.

For example, consider the following GET method.

Example: FormUri
public class StudentController : ApiController
{
    public Student Get([FromUri] Student stud)
    {

    }
}

In the above example, the Get() method includes a complex type parameter with the [FromUri] attribute. So, Web API will try to get the value of the Student type parameter from the query string. For example, if an HTTP GET request http://localhost:xxxx/api/student?id=1&name=steve then Web API will create an object the Student type and set its id and name property values to the value of id and name query string parameter.

Note:
The name of the complex type's properties and the query string parameters must match.

In the same way, consider the following example of Post() method.

Example: FromUri
public class StudentController : ApiController
{
    public Student Post([FromUri]Student stud)
    {

    }
}

As you can see above, we have applied the [FromUri] attribute with the Student parameter. By default, Web API extracts the value of the complex type from the request body, but here, we have applied the [FromUri] attribute. So now, Web API will extract the value of the Student properties from the query string instead of the request body.

In the same way, apply the [FromBody] attribute to get the value of primitive data type from the request body instead of a query string, as shown below.

Example: FromBody
public class StudentController : ApiController
{
    public Student Post([FromBody]string name)
    {

    }
}

Following is a valid HTTP POST request in the fiddler for the above action method.

Parameter Binding
Note:
The [FromBody] attribute can be applied on only one primitive parameter of an action method. It cannot be applied to multiple primitive parameters of the same action method.

The following figure summarizes parameter binding rules.

Web API Routing
Web API Parameter Bindings
Want to check how much you know Web API?