C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
134: Building a Minimal REST API from Scratch
Imagine you're opening a food truck. Now, if you were opening a five-star restaurant, you'd need a host to greet guests, waiters to take orders, a kitchen manager to coordinate, and a complex seating chart. That's basically what the full MVC (Model-View-Controller) pattern in .NET feels like—lots of structure, which is great for a skyscraper of an app, but overkill for a taco stand.
A Minimal API is that food truck. You've got one window. The customer walks up, asks for a specific item, and you hand it to them immediately. There's no middleman. You've stripped away the boilerplate so you can focus entirely on the actual "food"—the data your API provides.
Mapping the Truck to the Code
In a Minimal API, we map these real-world actions directly to C# methods:
- The Window: This is your
Route. It's the specific URL (like/books) where the request arrives. - The Order Type: This is your
HTTP Verb. AGETis like asking "Do you have tacos?", while aPOSTis like saying "I want to order a taco." - The Food: This is your
JSON Response. It's the actual data you send back to the client. - The Order Ticket: This is the
Request Body. If a user wants to add a new book, they send the details in a small packet of data.
Setting Up the Shop
We don't need a bunch of separate files for this. We can do it all in Program.cs. I'll use a "Digital Bookshelf" as our example because it's simple enough to follow but covers all the basics of data handling.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// Our "database" for now—just a simple list in memory
var books = new List<Book>
{
new Book(1, "The Fellowship of the Ring", "J.R.R. Tolkien"),
new Book(2, "Neuromancer", "William Gibson")
};
// We'll define our routes here...
app.Run();
public record Book(int Id, string Title, string Author);
Notice I used a record for the Book. Records are perfect for APIs because they're immutable and concise. Since we're just moving data around, we don't need a full-blown class with getters and setters.
Handling the Requests
Now we need to actually map the routes. This is where the "Minimal" part really shines. Instead of creating a BooksController class, we just call MapGet or MapPost directly on the app object.
// Get all books
app.MapGet("/books", () => books);
// Get a specific book by ID
app.MapGet("/books/{id}", (int id) =>
{
var book = books.FirstOrDefault(b => b.Id == id);
return book is not null ? Results.Ok(book) : Results.NotFound();
});
// Add a new book
app.MapPost("/books", (Book book) =>
{
books.Add(book);
return Results.Created($"/books/{book.Id}", book);
});
I've used a few different patterns here. The first one is a simple lambda that returns the whole list. .NET is smart enough to automatically turn that list into JSON. For the second one, I used Results.Ok and Results.NotFound. You want to do this because it tells the client exactly what happened via HTTP status codes (200 for success, 404 for missing), which is the "law of the land" for REST APIs.
A Note on State
You'll notice that books is just a local list. In a real app, you'd inject a database context here. But for a minimal service or a prototype, this in-memory approach is a lifesaver for speed. Just remember: every time you restart the app, your "bookshelf" resets to the original two books. It's a volatile state, but it's perfect for testing your logic before you commit to a heavy SQL Server setup.
📋 Practical Task
Build a Minimal Movie Rental Catalog
Your task is to expand on the Digital Bookshelf concept to create a Movie Rental API. You need to build a service that allows a user to track which movies are available for rent.
Requirements:
- Create a
Movierecord containing anId(int),Title(string), andIsRented(bool). - Initialize a list with at least three movies.
- Implement a
GET /moviesendpoint that returns the full list of movies. - Implement a
GET /movies/{id}endpoint that returns a specific movie or a 404 if not found. - Implement a
PATCH /movies/{id}/rentendpoint. This endpoint should find the movie by ID and flip theIsRentedvalue totrue, then return the updated movie. (Hint: Since records are immutable, you'll need to replace the movie in the list or use a class instead of a record for the Movie model).
There are no comments for now.