Implementing CRUD (Create, Read, Update, Delete) operations is fundamental to building any Web API. These operations allow clients to interact with your data in a meaningful way. This lesson will guide you through implementing these operations in your ASP.NET Core Web API, building upon the foundation we established in the previous lessons. We'll focus on creating API endpoints that handle different HTTP methods (POST, GET, PUT, DELETE) and interact with a data source.

Understanding CRUD Operations and HTTP Methods

CRUD is an acronym that stands for Create, Read, Update, and Delete. These are the four basic operations that can be performed on data. In the context of Web APIs, each CRUD operation is typically mapped to a specific HTTP method:

Setting up the Project

Let's assume you have a basic ASP.NET Core Web API project set up, as covered in the previous lesson. We'll continue with the "Books" example. If you don't have a project, create a new one using the ASP.NET Core Web API template in Visual Studio or VS Code.

First, let's define a simple Book model:

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
}

Next, we'll need a way to store and manage our books. For simplicity, we'll use an in-memory list. In a real-world application, you would typically use a database.

public class BookRepository
{
    private static List<Book> _books = new List<Book>();
    private static int _nextId = 1;

    public List<Book> GetAll()
    {
        return _books;
    }

    public Book? GetById(int id)
    {
        return _books.FirstOrDefault(b => b.Id == id);
    }

    public Book Add(Book book)
    {
        book.Id = _nextId++;
        _books.Add(book);
        return book;
    }

    public void Update(Book book)
    {
        var existingBook = _books.FirstOrDefault(b => b.Id == book.Id);
        if (existingBook != null)
        {
            existingBook.Title = book.Title;
            existingBook.Author = book.Author;
        }
    }

    public void Delete(int id)
    {
        var bookToRemove = _books.FirstOrDefault(b => b.Id == id);
        if (bookToRemove != null)
        {
            _books.Remove(bookToRemove);
        }
    }
}

Creating the API Controller

Now, let's create an API controller named BooksController to handle the CRUD operations.

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
    private readonly BookRepository _bookRepository;

    public BooksController()
    {
        _bookRepository = new BookRepository();
    }

    // GET: api/Books
    [HttpGet]
    public ActionResult<IEnumerable<Book>> GetBooks()
    {
        return _bookRepository.GetAll();
    }

    // GET: api/Books/5
    [HttpGet("{id}")]
    public ActionResult<Book> GetBook(int id)
    {
        var book = _bookRepository.GetById(id);

        if (book == null)
        {
            return NotFound();
        }

        return book;
    }

    // POST: api/Books
    [HttpPost]
    public ActionResult<Book> CreateBook(Book book)
    {
        var createdBook = _bookRepository.Add(book);

        // Return a 201 Created response with the new book and location header
        return CreatedAtAction(nameof(GetBook), new { id = createdBook.Id }, createdBook);
    }

    // PUT: api/Books/5
    [HttpPut("{id}")]
    public IActionResult UpdateBook(int id, Book book)
    {
        if (id != book.Id)
        {
            return BadRequest();
        }

        var existingBook = _bookRepository.GetById(id);
        if (existingBook == null)
        {
            return NotFound();
        }

        _bookRepository.Update(book);

        return NoContent(); // 204 No Content
    }

    // DELETE: api/Books/5
    [HttpDelete("{id}")]
    public IActionResult DeleteBook(int id)
    {
        var book = _bookRepository.GetById(id);
        if (book == null)
        {
            return NotFound();
        }

        _bookRepository.Delete(id);

        return NoContent(); // 204 No Content
    }
}

Explanation of the Code