FromQuery? FromForm? What do the .NET Web API attributes do?

Published: Sunday 28 May 2023

There are many From attributes including FromQuery and FromForm when adding a parameter to a controller's action in an ASP.NET Core Web API or MVC app. But what do these attributes do? And more importantly, how can we get them to work? We'll have a look at each one and give a C# code snippets to make it work.

FromQuery attribute

The FromQuery attribute is used for getting a querystring parameter. We can add the FromQuery attribute to an action parameter and by default, it will map the parameter name with the corresponding querystring name.

In this example, if we do a HTTP GET request for /api/from-api/from-query?page=4, the page parameter would have a value of 4 and that value would be returned as part of the response.

[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{
	[HttpGet("from-query")]
	public IActionResult FromQuery([FromQuery] int page)
	{
		return Ok(new { page });
	}
	...
}
URL Method Parameter attribute, name & value
/api/from-api/from-query?page=4 GET [FromQuery] int page = 4

When using the FromQuery attribute, there is an optional Name parameter that can be added. This is used when the action's parameter name is different to the querystring name.

For example, running /api/from-api/from-query?p=8 would map the page parameter in the action to 8. This is because it's decorated with the FromQuery attribute with a Name of p.

// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{
	...

	[HttpGet("from-query-with-name")]
	public IActionResult FromQueryWithName([FromQuery(Name = "p")] int page)
	{
		return Ok(new { page });
	}
	...
}
URL Method Parameter attribute, name & value
/api/from-api/from-query-with-name?p=8 GET [FromQuery(Name="p")] int page = 8

FromHeader attribute

The FromHeader works in a similar way to the FromQuery. For this, it maps the parameter to the corresponding request header based on the name.

An example of this is using authentication. If we are using JWT authentication in a Web API, we need to add an Authorization header to the request. If we want to get the value of the Authorization header, we can pass in a parameter with a name of authorization and add the FromHeader attribute to it.

// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{
	...
	[HttpGet("from-header")]
	public IActionResult FromHeader([FromHeader] string authorization)
	{
		return Ok(new { authorization });
	}
	...
}
URL Method Headers Parameter attribute, name & value
/api/from-api/from-header GET Authorization: Bearer abcd [FromHeader] string authorization = "Bearer abcd"

Once again, we can use the optional Name parameter in FromHeader if we wish to use a different parameter name to the header name.

For this, we have mapped the auth parameter in the controller's action so it maps it to the Authorization header in the request.

// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{
	...
	[HttpGet("from-header-with-name")]
	public IActionResult FromHeaderWithName([FromHeader(Name = "Authorization")] string auth)
	{
		return Ok(new { auth });
	}
	...
}
URL Method Headers Parameter attribute, name & value
/api/from-api/from-header-with-name GET Authorization: Bearer abcd [FromHeader(Name="Authorization")] string auth = "Bearer abcd"

FromForm attribute

The FromForm works in a HTTP post request if the multipart/form-data or x-www-url-encoded content type is used.

Again, it will map the form field name with the parameter name. By using the Name parameter in FromForm, it will map it against the name of the form field that is specified in that.

// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{      
	...
	[HttpPost("from-form")]
	public IActionResult FromForm([FromForm] string name)
	{
		return Ok(new { name });
	}    
	 
	[HttpPost("from-form-with-name")]
	public IActionResult FromFormWithName([FromForm(Name = "name")] string fullName)
	{
		return Ok(new { fullName });
	}
	...
}
URL Method Content-Type Form values Parameter attribute, name & value
/api/from-api/from-form POST multipart/form-data name=David Grace [FromForm] string name = "David Grace"
/api/from-api/from-form-with-name POST multipart/form-data name=David Grace [FromForm(Name = "name")] string fullName = "David Grace"

FromRoute attribute

The FromRoute is used if a route attribute is used as part of the action. By adding FromRoute to the action's parameter, it can get the value based on the name of the route attribute.

With the following example, there is a route attribute named {category}. By default, the FromRoute would map this attribute to a parameter name of category. This can be overridden by specifying the name of the route attribute as part of the Name parameter in the FromRoute attribute.

// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{
	...
	[HttpGet("from-route/{category}")]
	public IActionResult FromRoute([FromRoute] string category)
	{
		return Ok(new { category });
	}

	[HttpGet("from-route-with-name/{category}")]
	public IActionResult FromRouteWithName([FromRoute(Name = "category")] string categoryName)
	{
		return Ok(new { categoryName });
	}
	...
}
URL Method Parameter attribute, name & value
/api/from-api/from-route/blazor GET [FromRoute] string category = "blazor"
/api/from-api/from-route-with-name/blazor GET [FromRoute(Name = "category")] string categoryName = "blazor"

FromServices attribute

The FromServices attribute is the odd one out as it has nothing to do with a HTTP request. Instead, it allows us to use an action parameter to map a service from the IoC container using dependency injection.

In this instance, the FromServices attribute is not required if the controller is mapped with the ApiController attribute.

// IDateTimeService.cs
public interface IDateTimeService
{
	DateTime GetUtcNow();
}
// DateTimeService.cs
public class DateTimeService : IDateTimeService
{
	public DateTime GetUtcNow()
	{
		return DateTime.UtcNow;
	}
}
// Program.cs
...
builder.Services.AddSingleton<IDateTimeService, DateTimeService>();
...
// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{        
	...
	[HttpGet("from-services")]
	public IActionResult FromServices(IDateTimeService dateTimeService)
	{
		return Ok(new { now = dateTimeService.GetUtcNow() });
	}
	...
}

However, without the ApiController attribute, it throws an error. That is where we need to add the FromServices attribute to the action's parameter so it knows to map the service from the IoC container and use dependency injection.

// FromMvcController.cs
[Route("api/from-mvc")]
public class FromMvcController : Controller
{
	[HttpGet("from-services")]
	public IActionResult FromServices([FromServices] IDateTimeService dateTimeService)
	{
		return Ok(new { now = dateTimeService.GetUtcNow() });
	}
	...
}

What is the ApiController attribute?

The ApiController attribute is added to a controller when the actions within it are used to serve API responses.

They are configured with features and behaviour that help the developer experience for building APIs.

Some API specific behaviours including triggering an automatic HTTP 400 response if the ModelState is not valid and problem details for error status codes.

There is more information about the ApiController attribute on the Microsoft website.

FromBody attribute

The FromBody attribute is used when using the application/json content type and passing in JSON as part of the body.

However, this attribute only needs to use to be used when the ApiController attribute is not present in the controller.

As a rule, the FromBody can only be used for one parameter in an action. Therefore, in the likehood that there is more than one value being passed in the JSON body, each property needs to be added to a class, and this class is used as the type for the action parameter.

// Customer.cs
public class Customer
{
	public string Forename { get; init; }

	public string Surname { get; init; }
}
// FromApiController.cs
[ApiController]
[Route("api/from-api")]
public class FromApiController : Controller
{
	...

	[HttpPost("from-body")]
	public IActionResult FromBody(Customer customer)
	{
		return Ok(new { customer.Forename, customer.Surname });
	}
}
// FromMvcController.cs
[Route("api/from-mvc")]
public class FromMvcController : Controller
{
	...

	[HttpPost("from-body")]
	public IActionResult FromBody([FromBody]string forename)
	{
		return Ok(new { forename });
	}
}
URL Method JSON Controller attribute Parameter attribute, name & value
/api/from-api/from-body POST { "forename": "David", "surname": "Grace" } [ApiController] Customer customer = { Forename = "David", Surname = "Grace" }
/api/from-mvc/from-body POST { "forename": "David", "surname": "Grace" } [FromBody]Customer customer = { Forename = "David", Surname = "Grace" }

See a demo of these attributes

Watch our video where we show you how to use these attributes. We'll show you an example for each attribute and execute it in Postman to show you the response.

In-addition, you can download the code example where you can download the ASP.NET Core web app used in this tutorial. In-addition, there is a Postman import script so you can execute the endpoints for yourself.