This post is going to take the Contacts API from my ASP.NET Basics set of posts and move it from usingĀ IActionResult
toĀ ActionResult<T>
Ā which was introduced with the 2.1 release. The changes are really simple, but if you are using OpenAPI/Swagger I have a call out later in the post about something I noticed. The code before any changes can be found here.
IActionResult vs ActionResult<T>
The official docsĀ explain the three different ways to return data in an API which are a specific type, IActionResult
Ā type, or ActionResult<T>
Ā type.
A specific type is great if you don’t have to do any sort of validation or the like, but as soon as you need to return a different HTTP status than OK is no longer sufficient. This is where you would have to move to IActionResult
.
IActionResult
Ā allows different HTTP statuses to be returned. In the following example,Ā NotFound
Ā is returned if a contact with the supplied ID isn’t found orĀ OK(contact)
Ā if a contact is found.
public async Task<IActionResult> GetContact([FromRoute] int id) { var contact = await _context.Contact .SingleOrDefaultAsync(m => m.Id == id); if (contact == null) { return NotFound(); } return Ok(contact); }
The advantage ofĀ ActionResult<T>
Ā it is the return type of the function is clear. You can see in the following example whereĀ GetContact
Ā has been changed to useĀ ActionResult<T>
Ā that if all goes well you will be dealing with aĀ Contact
Ā object in the end without the need to wrap the result in anĀ OK
.
public async Task<ActionResult<Contact>> GetContact([FromRoute] int id) { var contact = await _context.Contact .SingleOrDefaultAsync(m => m.Id == id); if (contact == null) { return NotFound(); } return contact; }
OpenAPI/Swagger
If you are using OpenAPI/Swagger in your project with a function with the following definitionĀ it will automatically pick up the return type if you switch to usingĀ ActionResult<T>
.
public async Task<ActionResult<Contact>> GetContact([FromRoute] int id)
The above function results in the following in OpenAPI/Swagger UI.
This is awesome and saves you from having toĀ ProducesResponseType
Ā attributes to your API functions. Just note that as soon as you do add aĀ ProducesResponseType
Ā for say aĀ NotFound
Ā response you will still need include a response forĀ OK
Ā with the proper type or you will lose the return type in the OpenAPI/Swagger UI.
I’m calling that last bit out because I spent time trying to figure out why all the samples I saw the return type was automatically picked up, but in my sample application it wasn’t.
Wrapping Up
I’m a huge fan ofĀ ActionResult<T>
Ā mostly because of the clarityĀ it adds to API function definitions. The fact that OpenAPI/Swagger can pick up on it in the simple cases is an added bonus.
If you are looking for more info check out theĀ Exploring ActionResult<T> in ASP.NET Core 2.1 post byĀ Joonas WestlinĀ in which there is more info on how the functionality is actually implemented. If you didn’t already make sure and check out theĀ Controller action return types in ASP.NET Core Web APIĀ page in the official docs for a detailed comparison of the return type options for APIs.
The completed code can be found here.
Also published on Medium.