Dotnet Minimal APIs
Minimal APIs in .NET
Section titled “Minimal APIs in .NET”Minimal APIs is one of the available programming models offered by Microsoft to create RESTful APIs in .NET.
The other mainly used programming model is using controllers.
Comparison
Section titled “Comparison”| Controllers | Minimal APIs | |
|---|---|---|
| Structure | Classes (controllers) and class methods (actions) | Functions (any lambda or method) |
| Configuration | Basic setup in startup. Main configuration through attributes (declarative) | Method calls, slight use of attributes |
| Focus | Clear structure. Widely understood. | Flexible, little code needed |
Quick reference
Section titled “Quick reference”https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-8.0
A first look
Section titled “A first look”dotnet new web -o MyMinimalApiwill give you a minimalistic dotnet solution, with one project containing one Program.cs that looks like this:
var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();You can run the project by using an IDE like Visual Studio, VS Code or Rider, or by using the command line:
dotnet runSpecifying routes
Section titled “Specifying routes”var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.MapGet("/", () => "This is a GET");app.MapPost("/", () => "This is a POST");app.MapPut("/", () => "This is a PUT");app.MapDelete("/", () => "This is a DELETE");
app.Run();Route handlers
Section titled “Route handlers”A route handler is what is being called, whenever a route matches the incoming request.
Route handlers can be a lambda expression, a local function, an instance method or a static method.
Route handlers can be synchronous or asynchronous.
Route handlers (2)
Section titled “Route handlers (2)”var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.MapGet("/inline", () => "This is an inline lambda");
var handler = () => "This is a lambda variable";app.MapGet("/lambdaVariable", handler);
string LocalFunction() => "This is local function";app.MapGet("/localFunction", LocalFunction);
var handler = new HelloHandler();app.MapGet("/instanceMethod", handler.Hello);
app.MapGet("/staticMethod", HelloHandler.HelloStatic);
app.Run();
class HelloHandler{ public string Hello() { return "Hello Instance method"; }
public static string HelloStatic() { return "Hello static method"; }}Structuring Minimal API projects
Section titled “Structuring Minimal API projects”When Minimal API projects get larger it might be wise to structure them. They don’t have to be defined in Program.cs.
Structuring Example
Section titled “Structuring Example”using MinAPISeparateFile;var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
TodoEndpoints.Map(app);
app.Run();namespace MinAPISeparateFile;
public static class TodoEndpoints{ public static void Map(WebApplication app) { app.MapGet("/", () => "get all todo items"); app.MapGet("/{id}", (int id) => $"get todo item {id}"); }}Route parameters
Section titled “Route parameters”You can use a route pattern to specify parameters that are passed in as part of the URL
var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.MapGet( "/users/{userId}/books/{bookId}", (int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");
app.Run();Route constraints
Section titled “Route constraints”var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.MapGet( "/todos/{id:int}", (int id) => db.Todos.Find(id));app.MapGet( "/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text));app.MapGet( "/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
app.Run();Parameter binding
Section titled “Parameter binding”Parameter binding is the process of converting request data into strongly typed parameters that are expressed by route handlers.
- Supported binding sources:
- Route values
- Query string
- Header
- Body (as JSON)
- Form values
- Services provided by dependency injection
Parameter binding example
Section titled “Parameter binding example”var builder = WebApplication.CreateBuilder(args);
// Added as servicebuilder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapPost("/{id}", (int id, // route int page, // query param Person person, // body [FromHeader(Name = "X-CUSTOM-HEADER")] string customHeader, // header Service service) => { }); // service
class Service { }record Person(string Name, int Age);Explicit parameter binding
Section titled “Explicit parameter binding”using Microsoft.AspNetCore.Mvc;var builder = WebApplication.CreateBuilder(args);builder.Services.AddSingleton<Service>();var app = builder.Build();
app.MapPost("/{id}", ([FromRoute] int id, [FromQuery(Name = "p")] int page, [FromServices] Service service, [FromBody] Person person, [FromHeader(Name = "Content-Type")] string contentType) => {});
class Service { }record Person(string Name, int Age);Responses
Section titled “Responses”Route handlers support the following types of return values:
| Result Type | Behavior |
|---|---|
IResult based | Framework calls IResult.ExecuteAsync |
string | Framework writes string directly to response |
T (Any other type) | Framework JSON-serializes the response |