The order does not exist. Now what?
Every .NET API answers this question many times a day, and there are two camps. One throws a NotFoundException and lets something upstream turn it into a 404. The other returns the error as a value. Both work. Both have real costs.
This post lists the pros and cons of each, shows numbers, and ends with the rule I use.
TL;DR
Return the errors a caller can expect: not found, conflict, validation failed. They are 4xx.
Throw what should never happen: a bug, a dead database. It is a 500.
You need both, and both should produce the same error shape.
The exception way
public async Task < OrderDto > GetAsync ( int id , CancellationToken ct ) { var order = await repo . FindAsync ( id , ct ) ?? throw new NotFoundException ( $ "Order {id} does not exist." ) ;
return order . ToDto ( ) ; }
Enter fullscreen mode
Exit fullscreen mode
Somewhere else, an IExceptionHandler or a middleware catches NotFoundException and writes the 404.
What is good
It is built in.…