Minimal API Fundamentals

Back

Loading concept...

Minimal APIs in ASP.NET: Your Express Lane to Web Magic

The Restaurant Analogy

Imagine you own a tiny food truck instead of a big fancy restaurant. You don’t need a huge kitchen, lots of staff, or complicated systems. You just need:

  • A window to take orders
  • A simple menu
  • Quick hands to make food

That’s Minimal APIs! They’re the food truck of ASP.NET web development. Simple, fast, and gets the job done without all the fancy stuff.


What is a Minimal API?

Think of building a LEGO house. The regular way (Controllers) means you need lots of special pieces, instruction books, and time. Minimal APIs are like building with just the basic bricks - simpler and quicker!

The Old Way vs The New Way

Old Way (Controllers): Like writing a long letter with formal language

[ApiController]
[Route("[controller]")]
public class HelloController
    : ControllerBase
{
    [HttpGet]
    public string Get()
    {
        return "Hello World!";
    }
}

New Way (Minimal API): Like sending a quick text message

var app = WebApplication
    .CreateBuilder(args)
    .Build();

app.MapGet("/hello",
    () => "Hello World!");

app.Run();

See how much shorter? Same result, fewer words!


Route Handlers: Your Order Takers

A route handler is like a waiter at your food truck window. When someone asks for something (visits a URL), the handler responds.

graph TD A["Customer visits /pizza"] --> B["Route Handler"] B --> C[Returns: Here's your pizza!]

Different Types of Handlers

Just like a waiter can take orders, serve food, or clean up, handlers can do different things:

Action HTTP Method Example
Get something GET Show menu
Send something POST Place order
Update something PUT Change order
Remove something DELETE Cancel order

Simple Handler Examples

// GET - Ask for something
app.MapGet("/menu",
    () => "Pizza, Burger, Tacos");

// POST - Send something new
app.MapPost("/order",
    () => "Order received!");

// PUT - Change something
app.MapPut("/order/1",
    () => "Order updated!");

// DELETE - Remove something
app.MapDelete("/order/1",
    () => "Order cancelled!");

Route Parameters: The Magic Blanks

Route parameters are like fill-in-the-blank questions. You leave a spot empty, and someone fills it in!

Example: Greeting by Name

Instead of making separate routes for every person:

// BAD - Don't do this!
app.MapGet("/hello/john", ...);
app.MapGet("/hello/mary", ...);
app.MapGet("/hello/bob", ...);

Use a parameter (blank space):

// GOOD - One route, many names!
app.MapGet("/hello/{name}",
    (string name) =>
    quot;Hello, {name}!");

Now /hello/John says “Hello, John!” And /hello/Sarah says “Hello, Sarah!”

Multiple Parameters

You can have many blanks:

app.MapGet("/user/{id}/post/{postId}",
    (int id, int postId) =>
    quot;User {id}, Post {postId}");

Visiting /user/5/post/42 returns “User 5, Post 42”

graph TD A["/user/{id}/post/{postId}"] --> B["id = 5"] A --> C["postId = 42"] B --> D["User 5, Post 42"] C --> D

Route Groups: Organizing Your Menu

Imagine your food truck menu has sections:

  • Burgers: Cheeseburger, Veggie Burger
  • Drinks: Cola, Water, Juice

Route Groups work the same way! They organize related routes together.

Without Groups (Messy)

app.MapGet("/burgers", ...);
app.MapGet("/burgers/cheese", ...);
app.MapGet("/burgers/veggie", ...);
app.MapGet("/drinks", ...);
app.MapGet("/drinks/cola", ...);

With MapGroup (Organized!)

var burgers = app.MapGroup("/burgers");
burgers.MapGet("/",
    () => "All burgers");
burgers.MapGet("/cheese",
    () => "Cheeseburger");
burgers.MapGet("/veggie",
    () => "Veggie burger");

var drinks = app.MapGroup("/drinks");
drinks.MapGet("/",
    () => "All drinks");
drinks.MapGet("/cola",
    () => "Cola");

Both do the same thing, but the grouped version is cleaner!

graph TD A["/burgers"] --> B["/burgers/"] A --> C["/burgers/cheese"] A --> D["/burgers/veggie"] E["/drinks"] --> F["/drinks/"] E --> G["/drinks/cola"]

MapGroup: The Super Organizer

MapGroup is like a folder on your computer. It groups related things together and gives them a shared starting path.

Why Use MapGroup?

  1. Less Typing: Don’t repeat /api/products every time
  2. Easy to Find: Related routes stay together
  3. Share Settings: Apply rules to all routes at once

Real Example: Pet Store API

var api = app.MapGroup("/api");

var cats = api.MapGroup("/cats");
cats.MapGet("/",
    () => "List all cats");
cats.MapGet("/{id}",
    (int id) => quot;Cat #{id}");
cats.MapPost("/",
    () => "Added a cat!");

var dogs = api.MapGroup("/dogs");
dogs.MapGet("/",
    () => "List all dogs");
dogs.MapGet("/{id}",
    (int id) => quot;Dog #{id}");

This creates:

  • /api/cats - All cats
  • /api/cats/5 - Cat #5
  • /api/dogs - All dogs
  • /api/dogs/3 - Dog #3

Parameter Binding: The Smart Reader

Parameter binding is like having a smart assistant who reads customer orders and understands exactly what they want!

ASP.NET looks at your request and automatically fills in the values for you.

Where Can Values Come From?

Source What It Is Example
Route The URL path /user/5
Query String After the ? ?page=2
Body Hidden data JSON payload
Header Extra info Authorization
graph LR A["Request"] --> B["Route: /user/5"] A --> C["Query: ?name=Jo"] A --> D["Body: JSON data"] B --> E["Automatic Binding"] C --> E D --> E E --> F["Your Handler Gets Values!"]

Query String Binding: The Question Asker

Query strings are like questions at the end of a URL. They come after the ? mark.

Example URL

/search?keyword=pizza&limit=10
         ↑            ↑
      Question 1   Question 2

Using Query Strings

app.MapGet("/search",
    (string keyword, int limit) =>
    quot;Searching for '{keyword}', " +
    quot;showing {limit} results");

When someone visits /search?keyword=pizza&limit=10, they get:

“Searching for ‘pizza’, showing 10 results”

Optional Query Parameters

Sometimes people don’t fill in everything. Use ? to make it optional:

app.MapGet("/products",
    (string? category,
     int? page) =>
{
    var cat = category ?? "all";
    var p = page ?? 1;
    return quot;Category: {cat}, " +
           quot;Page: {p}";
});
  • /products → Category: all, Page: 1
  • /products?category=toys → Category: toys, Page: 1
  • /products?page=3 → Category: all, Page: 3

Request Body Binding: The Hidden Message

Sometimes customers send you a detailed order - not just a few words, but a whole message! That’s the request body.

The Order Slip Analogy

Think of it like filling out an order form:

Name: John
Item: Large Pizza
Topping: Pepperoni
Address: 123 Main St

In code, we use a class to define what the order looks like:

// The order form template
public class Order
{
    public string Name { get; set; }
    public string Item { get; set; }
    public string Topping { get; set; }
}

// Reading the order
app.MapPost("/orders",
    (Order order) =>
    quot;Hi {order.Name}! " +
    quot;One {order.Item} with " +
    quot;{order.Topping} coming up!");

The customer sends JSON:

{
  "name": "John",
  "item": "Large Pizza",
  "topping": "Pepperoni"
}

And you get: “Hi John! One Large Pizza with Pepperoni coming up!”

graph TD A["Customer sends JSON"] --> B["ASP.NET reads it"] B --> C["Creates Order object"] C --> D["Your handler uses it"] D --> E["Response: Hi John!..."]

Putting It All Together: The Complete Food Truck

Let’s build a mini food truck API using everything we learned:

var builder = WebApplication
    .CreateBuilder(args);
var app = builder.Build();

// Route Group for all menu items
var menu = app.MapGroup("/menu");

// GET all items
menu.MapGet("/",
    () => new[] {
        "Pizza",
        "Burger",
        "Tacos"
    });

// GET one item by name (parameter)
menu.MapGet("/{item}",
    (string item) =>
    quot;You selected: {item}");

// Search with query string
app.MapGet("/search",
    (string? q, int? limit) =>
{
    var query = q ?? "";
    var max = limit ?? 10;
    return quot;Searching '{query}' " +
           quot;(max {max})";
});

// Create order with body
app.MapPost("/order",
    (Order order) =>
    quot;Order for {order.Name}: " +
    quot;{order.Item}");

app.Run();

public class Order
{
    public string Name { get; set; }
    public string Item { get; set; }
}

Quick Reference Card

Concept What It Does Example
Minimal API Simple web API app.MapGet(...)
Route Handler Responds to requests () => "Hello"
Route Parameter Dynamic URL parts /{id}
MapGroup Organizes routes app.MapGroup("/api")
Query String URL questions ?page=2
Body Binding JSON to object (Order o)

You Did It!

You just learned how to:

  • Create simple APIs without all the fuss
  • Handle different types of requests
  • Use parameters to make flexible routes
  • Organize routes into groups
  • Read data from URLs and request bodies

Minimal APIs are your new superpower! They’re perfect for:

  • Quick prototypes
  • Small services
  • Learning web development
  • When you want simplicity

Now go build something amazing! Your food truck is ready to serve the web!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.