Step 3: Routes and controller
This step adds a resource controller and the routes to list, create and show posts.
1. Make the controller
-r makes a resource controller with the seven CRUD methods.
Replace the file with this. It keeps only index, store and show:
lib/app/http/controllers/post.controller.dart
import 'package:blog/app/models/post/post.model.dart';
import 'package:dox_core/dox_core.dart';
class PostController {
/// GET /api/posts
Future<List<Post>> index(DoxRequest req) async {
return Post().all();
}
/// POST /api/posts
Future<DoxResponse> store(DoxRequest req) async {
Post post = Post()
..title = req.input('title')
..body = req.input('body');
await post.save();
return response(post).statusCode(201);
}
/// GET /api/posts/{id}
Future<Post> show(int id) async {
Post? post = await Post().find(id);
if (post == null) {
throw NotFoundHttpException();
}
return post;
}
}
PostController postController = PostController();
How it works:
- A controller returns a model or a list of models. Dox sends it as JSON.
response(post).statusCode(201)sets the status code.show(int id)gets the{id}from the URL./api/posts/abcanswers404, becauseabcis not anint.req.input('title')reads the body as it is. It is not checked yet. Step 4 fixes that.
2. Add the routes
lib/routes/api.dart
import 'package:blog/app/http/controllers/api.controller.dart';
import 'package:blog/app/http/controllers/post.controller.dart';
import 'package:dox_core/dox_core.dart';
class ApiRouter extends Router {
@override
String get prefix => 'api';
@override
List<dynamic> get middleware => <dynamic>[];
@override
void register() {
Route.get('/ping', apiController.pong);
Route.resource('posts', postController);
}
}
Route.resource makes one route for each method the controller has:
| Method | Path | Controller method |
|---|---|---|
GET |
/api/posts |
index |
POST |
/api/posts |
store |
GET |
/api/posts/{id} |
show |
The controller has no update or destroy, so those routes are not made.
3. Start the server
If it is still running from step 1, it restarts by itself.
Check it
Make a post:
curl -i -X POST http://localhost:3000/api/posts \
-H 'Content-Type: application/json' \
-d '{"title":"Hello Dox","body":"My first post."}'
HTTP/1.1 201 Created
content-type: application/json; charset=utf-8
...
{"id":1,"title":"Hello Dox","body":"My first post.","created_at":"2026-10-22T13:58:14.062215Z","updated_at":"2026-10-22T13:58:14.062215Z"}
List the posts:
[{"id":1,"title":"Hello Dox","body":"My first post.","created_at":"2026-10-22T13:58:14.062215Z","updated_at":"2026-10-22T13:58:14.062215Z"}]
Show one post:
{"id":1,"title":"Hello Dox","body":"My first post.","created_at":"2026-10-22T13:58:14.062215Z","updated_at":"2026-10-22T13:58:14.062215Z"}
A post that does not exist: