ASP.NET Core › Controllers vs Minimal APIs
How do action results like Ok(), NotFound(), and BadRequest() in controllers compare to their minimal API equivalents like Results.Ok() and TypedResults?
IntermediateAnswer
Controllers use IActionResult-returning helper methods (Ok(), NotFound(), BadRequest()) inherited from ControllerBase, while minimal APIs use the static Results class (Results.Ok(), Results.NotFound()) or the newer, more strongly-typed TypedResults class (introduced for better OpenAPI metadata generation and compile-time type safety) -- both express equivalent HTTP semantics, just through different APIs suited to each style's conventions.
// Controller
public IActionResult GetProduct(int id) {
var product = _service.GetById(id);
return product is null ? NotFound() : Ok(product);
}
// Minimal API with TypedResults (better OpenAPI metadata)
app.MapGet("/products/{id}", Results<Ok<Product>, NotFound> (int id, IProductService service) => {
var product = service.GetById(id);
return product is null ? TypedResults.NotFound() : TypedResults.Ok(product);
});Real-world example A minimal API adopts TypedResults over the plain Results class specifically because its strongly-typed return signature lets OpenAPI tooling automatically infer and document every possible response type (200 and 404) without needing separate ProducesResponseType annotations.