An action is a method within a controller that processes an incoming request and returns a response of a specific type.
The return type of the action determines how the framework will serialize and send the response to the client, directly affecting the format, HTTP status code, and headers of the response.
- HTTP status codes communicate the result of the operation
- Return types define the structure of the returned data
Together, they form the universal language that client applications (such as frontends or mobile apps) will use to understand how to process our responses.
Returning results in an action method
The most common return type in ASP.NET for action methods is ActionResult
and its derivatives,
Return Type | Description |
---|---|
ActionResult | Flexible base class for HTTP response |
ActionResult<T> | Combines data with HTTP status codes |
IActionResult | Interface that allows returning any type of result |
Depending on the type of result we want to send, we can use various classes and objects. Let’s look at the most common options.
It is useful when you do not need to return a specific object, but simply communicate the result of an operation.
[HttpPost("login")]
public ActionResult Login(UserLoginDto loginDto)
{
if (!_authService.IsValidUser(loginDto))
return Unauthorized(); // 401 if credentials are invalid
var token = _authService.GenerateToken(loginDto.Username);
return Ok(new { token }); // 200 OK with JWT token
}
This approach is very common in endpoints that handle authentication, state operations, or simple responses without a fixed model.
When you need to return data along with an appropriate HTTP status, we use ActionResult<T>
.
It allows returning both the object T
and specific HTTP status codes:
[HttpGet("products/{id}")]
public ActionResult<ProductDto> GetProduct(int id)
{
var product = _productService.GetById(id);
if (product == null)
return NotFound(); // 404 Not Found
return product; // 200 OK + JSON of the product
}
This pattern is ideal for modern RESTful APIs that must communicate the success or failure of the operation along with the content.
IActionResult
is the most flexible option and is typically used when the exact type of response can vary widely depending on the method’s logic.
When we need to return different types of objects in the same endpoint, IActionResult
is the choice:
[HttpGet("report")]
public IActionResult GetReport(bool detailed)
{
if (detailed)
return Ok(_reportService.GetDetailedReport()); // 200 OK with JSON
return Content(_reportService.GetSummary(), "text/plain"); // 200 OK with plain text
}
This approach allows for more dynamic logic, although with less type control.
Derived Types
These methods are derived from ActionResult and encapsulate both the content of the response and the appropriate HTTP status code.
Using them allows clearly expressing the intent of the controller and maintaining the correct HTTP semantics in our APIs.
Type | HTTP Code | When to use it |
---|---|---|
Ok | 200 OK | Successful GET operations |
Created | 201 Created | Successful POST |
Accepted | 202 Accepted | Background processing |
NoContent | 204 No Content | Successful DELETE/PUT without return data |
return Ok(product); // HTTP 200
return Created($"/products/{id}", product); // HTTP 201
return Accepted(); // HTTP 202
return NoContent(); // HTTP 204
Type | HTTP Code | When to use it |
---|---|---|
BadRequestObject | 400 Bad Request | Failed validations or invalid data |
Unauthorized | 401 Unauthorized | Missing authentication |
Forbid | 403 Forbidden | Authenticated user but lacks permissions |
NotFound | 404 Not Found | GET/PUT/DELETE of a non-existent resource |
return BadRequest("Detailed message"); // HTTP 400
return Unauthorized(); // HTTP 401
return Forbid(); // HTTP 403
return NotFound(); // HTTP 404
Type | HTTP Code | When to use it |
---|---|---|
StatusCode | Customizable | Special cases (e.g., 429 Too Many Requests) |
return StatusCode(429); // Custom code
return File(bytes, "image/png"); // File download
return PhysicalFile("/path", "text/csv"); // Physical file
:::: :::::
Other return types
In addition to ActionResult
and IActionResult
, action methods in ASP.NET can directly return simple values.
Return Type | Description |
---|---|
Direct return | Simple return that is automatically serialized |
View() | Returns a view in MVC applications |
In some cases, it may be necessary to return a value directly from an action method.
public int Sum(int a, int b)
{
return a + b; // Returns the value directly
}
Or even return an object directly (like ProductDto
).
public IEnumerable<ProductDto> GetAllProducts()
{
return _productService.GetAll();
}
In this case, ASP.NET automatically converts the value into an HTTP response (always returns 200).
Avoid direct return types, as we lose the flexibility to represent errors or other HTTP states.
In MVC (Model-View-Controller) applications, it is used in web applications.
In this type of application, to return a view from an action method, we use the View()
method.
public View Details(int id)
{
var product = GetProductById(id);
return View(product); // Returns the "Details" view with a product model
}
Here, the Details
method receives an id
parameter and looks up the corresponding product. It then returns a view with the product details, using the data model product
.
Redirects
In some situations, an action does not need to return content directly, but rather redirect the client to another location.
ASP.NET provides methods for performing redirects, either to external URLs or to other actions within the application itself.
Return Type | Description |
---|---|
Redirect(string url) | Redirect to an external URL |
RedirectToAction(...) | Redirect to another action method |
In some situations, it is necessary to redirect the user to a specific URL outside of the application.
This can be done using Redirect
.
public ActionResult GoToGoogle()
{
return Redirect("https://www.google.com"); // Redirects the user to Google
}
At times, it is necessary to redirect the request to another action method, either within the same controller or to a different controller.
This can be done using the RedirectToAction
statement.
public ActionResult CreateProduct(Product product)
{
// Logic to create the product in the database
return RedirectToAction("Index"); // Redirects to the Index method
}
In this example, the CreateProduct
method processes the request to create a product. After performing the operation, it redirects the user to the Index
method.
These responses typically use the HTTP status code 302 (Found), although they can also be customized to use other codes such as 301 (Moved Permanently) or 307 (Temporary Redirect).