ASP.NET Core API - ActionResult<T> vs async Task<T>
ASP.NET Core offers the following options for Web API controller action return types:
Specific type (T)
IActionResult
ActionResult<T>
Specific type (T):
The Specific
return type is appropriate when you need to return primitive or complex data type without further checking with possibility of different return type (BadRequestResult (400),
NotFoundResult (404), and
OkObjectResult(200)`.) from the action as follows:
[HttpGet]
public async Task<List<Product>> GetProducts()
{
return await _repository.GetProductsAsync();
// Here you can not return Ok(products), NotFound() etc;
// If you need to return NotFound() etc then use `IActionResult` instead of Specific type.
}
IActionResult type:
The IActionResult
return type is appropriate when multiple ActionResult
return types are possible in an action as follows:
[HttpGet]
public async Task<IActionResult> GetProductById(int id)
{
Product product = await _repository.GetProductByIdAsync(id);
if(product == null)
{
return NotFound(); // Here is one return type
}
return Ok(product); // Here is another return type
}
The ActionResult
types represent various HTTP status codes. Some common return types falling into this category are BadRequestResult (400)
, NotFoundResult (404)
, and OkObjectResult(200)
.
ActionResult<T>
type:
ASP.NET Core 2.1 adds new programming conventions that make it easier to build clean and descriptive web APIs. ActionResult<T>
is a new type added to allow an app to return either a response type or any other action result (similar to IActionResult
), while still indicating the response type.
ActionResult<T>
is more specific to Web APIs in ASP.NET Core >= 2.1 and ActionResult<T>
offers the following benefits over the IActionResult
type:
- The
[ProducesResponseType]
attribute's Type property can be excluded. For example,[ProducesResponseType(200, Type = typeof(Product))]
is simplified to[ProducesResponseType(200)]
. The action's expected return type is instead inferred from theT
inActionResult<T>
. - Implicit cast operators support the conversion of both
T
andActionResult
toActionResult<T>
.T
converts toObjectResult
, which means return newObjectResult(T);
is simplified toreturn T;
.
For more details: Controller action return types in ASP.NET Core Web API
Third solution: IActionResult Task, something like this:
[HttpGet]
[ProducesResponseType(typeof(IList<Currency>), 200)]
public async Task<IActionResult> GetAll()
{
return Ok(await _typeService.GetCurrenciesAsync().ConfigureAwait(false));
}
[HttpGet("{id}", Name = "GetCurrency")]
[ProducesResponseType(typeof(Currency), 200)]
public async Task<IActionResult> Get([FromRoute]int id)
{
return Ok(await _expenseService.GetCurrencyAsync(id).ConfigureAwait(false));
}
Have a look at an example from Microsoft and why they return the interface instead: IActionResult