ASP.NET Core 8 Web API -

Actions

Actions in ASP.NET Core 8 Web API are the methods in controllers that respond to HTTP requests. Each action corresponds to a route and performs a specific task, such as retrieving data, creating a new record, or updating an existing record. This guide will provide a detailed overview of actions, best practices, and examples.


1. Introduction to Actions

In ASP.NET Core, actions are methods within a controller class that handle HTTP requests. They are typically decorated with HTTP method attributes like [HttpGet], [HttpPost], [HttpPut], and [HttpDelete].


2. Defining Actions

An action method is defined in a controller class, which is derived from ControllerBase or Controller. Here’s a basic example:

        
            
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult GetAll()
    {
        // Retrieve all products
        return Ok(new List<Product>());
    }
}

        
    

[ApiController]: Indicates that the controller responds to web API requests.
[Route("api/[controller]")]: Sets the base route for the controller.
[HttpGet]: Indicates that this action handles HTTP GET requests.
IActionResult: Represents the result of an action method.


3. HTTP Method Attributes

ASP.NET Core provides several attributes to specify the HTTP method an action responds to:

        
            
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        // Retrieve order by ID
        return Ok(new Order { Id = id });
    }

    [HttpPost]
    public IActionResult Create(Order order)
    {
        // Create a new order
        return CreatedAtAction(nameof(GetById), new { id = order.Id }, order);
    }

    [HttpPut("{id}")]
    public IActionResult Update(int id, Order order)
    {
        // Update an existing order
        return NoContent();
    }

    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        // Delete an order by ID
        return NoContent();
    }
}

        
    

4. Action Parameters

Actions can have parameters that come from various sources such as route data, query strings, and request bodies. Here are examples of different types of action parameters:

        
            
[ApiController]
[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        // Retrieve customer by ID (route parameter)
        return Ok(new Customer { Id = id });
    }

    [HttpGet]
    public IActionResult Search([FromQuery] string name)
    {
        // Search customers by name (query string parameter)
        return Ok(new List<Customer>());
    }

    [HttpPost]
    public IActionResult Create([FromBody] Customer customer)
    {
        // Create a new customer (body parameter)
        return CreatedAtAction(nameof(GetById), new { id = customer.Id }, customer);
    }
}

        
    

Route parameters: Specified in the route template and passed to the action method.
Query string parameters: Extracted from the URL query string.
Body parameters: Deserialized from the request body.


5. Returning Results

Actions can return various types of results, including simple data, complex objects, or HTTP responses. Here are some examples:

        
            
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public ActionResult<List<Product>> GetAll()
    {
        return Ok(new List<Product>());
    }

    [HttpGet("{id}")]
    public ActionResult<Product> GetById(int id)
    {
        var product = new Product { Id = id };
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    [HttpPost]
    public ActionResult<Product> Create(Product product)
    {
        return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
    }

    [HttpPut("{id}")]
    public IActionResult Update(int id, Product product)
    {
        return NoContent();
    }

    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        return NoContent();
    }
}

        
    

Ok(result): Returns a 200 OK response with the specified result.
NotFound(): Returns a 404 Not Found response.
CreatedAtAction(actionName, routeValues, value): Returns a 201 Created response with a Location header.
NoContent(): Returns a 204 No Content response.


6. Validation

You can use data annotations to validate action parameters and model properties. Here's an example of using validation in an action:

        
            
public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Range(0, 100)]
    public decimal Price { get; set; }
}

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpPost]
    public IActionResult Create([FromBody] Product product)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
    }
}

        
    

[Required]: Ensures the property is not null.
[Range(min, max)]: Ensures the property value falls within the specified range.
ModelState.IsValid: Checks if the model state is valid based on the data annotations.


7. Asynchronous Actions

Asynchronous programming improves the scalability of your web API by freeing up threads while waiting for I/O operations to complete. Here’s an example of an asynchronous action:

        
            
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductRepository _repository;

    public ProductsController(IProductRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public async Task<IActionResult> GetAll()
    {
        var products = await _repository.GetAllAsync();
        return Ok(products);
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(int id)
    {
        var product = await _repository.GetByIdAsync(id);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] Product product)
    {
        await _repository.AddAsync(product);
        return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> Update(int id, [FromBody] Product product)
    {
        await _repository.UpdateAsync(id, product);
        return NoContent();
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(int id)
    {
        await _repository.DeleteAsync(id);
        return NoContent();
    }
}

        
    

8. Dependency Injection

Use dependency injection to manage service dependencies in your controllers:

        
            
public interface IProductService
{
    Task<List<Product>> GetAllAsync();
    Task<Product> GetByIdAsync(int id);
    Task AddAsync(Product product);
    Task UpdateAsync(int id, Product product);
    Task DeleteAsync(int id);
}

public class ProductService : IProductService
{
    // Implementation of IProductService
}

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    public async Task<IActionResult> GetAll()
    {
        var products = await _productService.GetAllAsync();
        return Ok(products);
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(int id)
    {
        var product = await _productService.GetByIdAsync(id);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] Product product)
    {
        await _productService.AddAsync(product);
        return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
    }

    [HttpPut("{id}")]
    public async Task<IActionResult> Update(int id, [FromBody] Product product)
    {
        await _productService.UpdateAsync(id, product);
        return NoContent();
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(int id)
    {
        await _productService.DeleteAsync(id);
        return NoContent();
    }
}

        
    

9. Best Practices for Actions


10. Summary

Actions are the core components of an ASP.NET Core Web API, responsible for handling HTTP requests and performing operations. By following best practices and leveraging features like dependency injection, model validation, and asynchronous programming, you can build robust and maintainable web APIs.