Skip to main content

How to Build a REST API with ASP.NET Core 8 (Step by Step)

Learn how to build a REST API with ASP.NET Core 8 step by step with runnable C# code, EF Core, CRUD endpoints, and best practices. Start building today!

If you want to build a REST API with ASP.NET Core, this step-by-step tutorial walks you through everything you need to ship a working, production-ready Web API in .NET 8. By the end of this guide you'll have a full CRUD REST API in C# backed by Entity Framework Core, complete with routing, dependency injection, validation, and Swagger documentation. This ASP.NET Core 8 Web API tutorial is written for beginners who are searching "how to create a REST API" as well as intermediate developers who want best practices they can drop into real projects.

What Is a REST API and Why ASP.NET Core 8?

A REST API (Representational State Transfer) exposes resources over HTTP using predictable verbs: GET to read, POST to create, PUT to update, and DELETE to remove. ASP.NET Core 8 is Microsoft's high-performance, cross-platform framework for building these APIs. It runs on Windows, Linux, and macOS, ships with built-in dependency injection, and consistently ranks among the fastest web frameworks in independent benchmarks.

Developers choose ASP.NET Core 8 to build a REST API with ASP.NET Core because of long-term support (LTS), first-class tooling in Visual Studio and the .NET CLI, and seamless integration with Entity Framework Core for database access. Whether you're in the USA, UK, Canada, Australia, or India, these skills are in high demand for backend and full-stack roles.

Prerequisites

  • The .NET 8 SDK installed (run dotnet --version to confirm 8.x).
  • Visual Studio 2022, VS Code, or JetBrains Rider.
  • Basic C# knowledge — classes, methods, and async/await.

Step 1: Create the ASP.NET Core 8 Web API Project

Open a terminal and scaffold a new Web API. Using the .NET CLI keeps the steps identical across every operating system:

dotnet new webapi -n BookStoreApi --use-controllers
cd BookStoreApi
dotnet run

The --use-controllers flag gives you the controller-based template (rather than Minimal APIs), which is ideal when you want clear separation and scalability. When the app starts, browse to the HTTPS URL shown in the console and append /swagger to see the auto-generated API documentation.

Step 2: Define Your Model

Every REST API revolves around resources. Create a Models folder and add a Book.cs class. Data annotations give you free validation later.

using System.ComponentModel.DataAnnotations;

namespace BookStoreApi.Models;

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

    [Required]
    [StringLength(200)]
    public string Title { get; set; } = string.Empty;

    [Required]
    [StringLength(100)]
    public string Author { get; set; } = string.Empty;

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

    public DateTime PublishedOn { get; set; }
}

Step 3: Add Entity Framework Core for Data Access

To persist data we'll use Entity Framework Core, the most common ORM for an ASP.NET Core Web API. Add the packages (we use the lightweight in-memory provider here so you can run this tutorial with zero database setup; swap it for SQL Server in production):

dotnet add package Microsoft.EntityFrameworkCore.InMemory
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Create a Data folder with an AppDbContext. The DbSet<Book> becomes your queryable table.

using BookStoreApi.Models;
using Microsoft.EntityFrameworkCore;

namespace BookStoreApi.Data;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options) { }

    public DbSet<Book> Books => Set<Book>();
}

Register the context with the built-in dependency injection container in Program.cs. This is why ASP.NET Core scales cleanly — services are configured once and injected everywhere.

using BookStoreApi.Data;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseInMemoryDatabase("BookStore"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

Step 4: Build the CRUD Controller

Now for the heart of the tutorial: a full CRUD API controller. Create Controllers/BooksController.cs. Each action maps to an HTTP verb and returns the correct status code — a hallmark of a well-designed REST API.

using BookStoreApi.Data;
using BookStoreApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace BookStoreApi.Controllers;

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

    public BooksController(AppDbContext context)
    {
        _context = context;
    }

    // GET: api/books
    [HttpGet]
    public async Task<ActionResult<IEnumerable<Book>>> GetBooks()
    {
        return await _context.Books.AsNoTracking().ToListAsync();
    }

    // GET: api/books/5
    [HttpGet("{id:int}")]
    public async Task<ActionResult<Book>> GetBook(int id)
    {
        var book = await _context.Books.FindAsync(id);
        return book is null ? NotFound() : book;
    }

    // POST: api/books
    [HttpPost]
    public async Task<ActionResult<Book>> CreateBook(Book book)
    {
        _context.Books.Add(book);
        await _context.SaveChangesAsync();
        return CreatedAtAction(nameof(GetBook), new { id = book.Id }, book);
    }

    // PUT: api/books/5
    [HttpPut("{id:int}")]
    public async Task<IActionResult> UpdateBook(int id, Book book)
    {
        if (id != book.Id) return BadRequest("Route id and body id must match.");

        _context.Entry(book).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException) when (!BookExists(id))
        {
            return NotFound();
        }

        return NoContent();
    }

    // DELETE: api/books/5
    [HttpDelete("{id:int}")]
    public async Task<IActionResult> DeleteBook(int id)
    {
        var book = await _context.Books.FindAsync(id);
        if (book is null) return NotFound();

        _context.Books.Remove(book);
        await _context.SaveChangesAsync();
        return NoContent();
    }

    private bool BookExists(int id) => _context.Books.Any(b => b.Id == id);
}

A few things make this controller idiomatic. The [ApiController] attribute enables automatic model validation (no manual ModelState.IsValid checks), automatic 400 responses, and binding-source inference. CreatedAtAction returns a 201 with a Location header pointing at the new resource — exactly what REST clients expect. And AsNoTracking() on read-only queries skips EF Core's change tracker for a real performance win.

Step 5: Test Your REST API

Run dotnet run and open Swagger UI. Try a POST to /api/books with this JSON body:

{
  "title": "Clean Code",
  "author": "Robert C. Martin",
  "price": 39.99,
  "publishedOn": "2008-08-01T00:00:00"
}

You can also test from the command line with curl, which works identically on Windows, macOS, and Linux:

curl -X POST https://localhost:5001/api/books \
  -H "Content-Type: application/json" \
  -d '{"title":"Clean Code","author":"Robert C. Martin","price":39.99,"publishedOn":"2008-08-01"}'

curl https://localhost:5001/api/books

ASP.NET Core Web API Best Practices

Once you can build a REST API with ASP.NET Core, these best practices separate a hobby project from production code:

  • Use DTOs, not entities. Returning EF Core entities directly leaks your database schema and risks over-posting attacks. Map to request/response DTOs instead.
  • Version your API. Add api/v1/books routes so you can evolve without breaking existing clients.
  • Return consistent error responses. ASP.NET Core 8's ProblemDetails (RFC 7807) gives standardized error payloads out of the box.
  • Page large result sets. Never return thousands of rows; accept page and pageSize query parameters.
  • Apply async all the way. Use async EF Core methods so threads aren't blocked on I/O — critical for scalability under load.
  • Secure it. Add JWT authentication and the [Authorize] attribute before going to production.

Common Pitfalls to Avoid

  • Forgetting status codes. Returning 200 for everything breaks REST clients. Use 201, 204, 400, 404 appropriately.
  • Synchronous database calls. Blocking calls like ToList() instead of ToListAsync() throttle throughput.
  • Over-posting. Binding directly to entities lets clients set fields they shouldn't — another reason to use DTOs.
  • Leaving Swagger enabled in production without protection can expose your full API surface.

Conclusion and Key Takeaways

You've now seen how to build a REST API with ASP.NET Core 8 from an empty folder to a fully working CRUD service. The same pattern — model, DbContext, controller, and tested endpoints — scales from a weekend project to enterprise microservices used by teams across the USA, UK, Canada, Australia, and India.

Key takeaways:

  • Scaffold quickly with dotnet new webapi and document automatically with Swagger.
  • Use Entity Framework Core and dependency injection for clean, testable data access.
  • Map HTTP verbs to controller actions and return correct status codes for a true REST API.
  • Apply DTOs, versioning, async, and authentication before shipping to production.

Next, swap the in-memory provider for SQL Server, add JWT auth, and deploy to Azure App Service or Docker. Bookmark csharp-coder.com and keep building — your ASP.NET Core 8 Web API skills are exactly what employers are searching for in 2026.

About csharp-coder.com
Your go-to resource for C#, .NET, and modern software development. Follow along for daily tutorials, tips, and real-world examples.

Comments

Popular posts from this blog

Angular 14 CRUD Operation with Web API .Net 6.0

How to Perform CRUD Operation Using Angular 14 In this article, we will learn the angular crud (create, read, update, delete) tutorial with ASP.NET Core 6 web API. We will use the SQL Server database and responsive user interface for our Web app, we will use the Bootstrap 5. Let's start step by step. Step 1 - Create Database and Web API First we need to create Employee database in SQL Server and web API to communicate with database. so you can use my previous article CRUD operations in web API using net 6.0 to create web API step by step. As you can see, after creating all the required API and database, our API creation part is completed. Now we have to do the angular part like installing angular CLI, creating angular 14 project, command for building and running angular application...etc. Step 2 - Install Angular CLI Now we have to install angular CLI into our system. If you have already installed angular CLI into your system then skip this step.  To install angular CLI ope...

Angular 14 : 404 error during refresh page after deployment

In this article, We will learn how to solve 404 file or directory not found angular error in production.  Refresh browser angular 404 file or directory not found error You have built an Angular app and created a production build with ng build --prod You deploy it to a production server. Everything works fine until you refresh the page. The app throws The requested URL was not found on this server message (Status code 404 not found). It appears that angular routing not working on the production server when you refresh the page. The error appears on the following scenarios When you type the URL directly in the address bar. When you refresh the page The error appears on all the pages except the root page.   Reason for the requested URL was not found on this server error In a Multi-page web application, every time the application needs to display a page it has to send a request to the web server. You can do that by either typing the URL in the address bar, clicking on the Me...

Send an Email via SMTP with MailKit Using .NET 6

How to Send an Email in .NET Core This tutorial show you how to send an email in .NET 6.0 using the MailKit email client library. Install MailKit via NuGet Visual Studio Package Manager Console: Install-Package MailKit How to Send an HTML Email in .NET 6.0 This code sends a simple HTML email using the Gmail SMTP service. There are instructions further below on how to use a few other popular SMTP providers - Gmail, Hotmail, Office 365. // create email message var email = new MimeMessage(); email.From.Add(MailboxAddress.Parse("from_address@example.com")); email.To.Add(MailboxAddress.Parse("to_address@example.com")); email.Subject = "Email Subject"; email.Body = new TextPart(TextFormat.Html) { Text = "<h1>Test HTML Message Body</h1>" }; // send email using var smtp = new SmtpClient(); smtp.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls); smtp.Authenticate("[Username]", "[Password]"); smtp.Se...