# Metadata
Metadata are used to add information to a class, a method, a property, or a parameter. In other programming languages they are easily accessible thanks to reflaction. But since they are really useful, Serinus provides his own way to add metadata to your routes and controllers.
::: info
Dart does not support reflection, so Serinus provides a more static way to add metadata to your classes.
:::
## Creating Metadata
To create a metadata, you need to extend the `Metadata` class. As simple as that.
```dart
import 'package:serinus/serinus.dart';
class IsPublic extends Metadata {
const IsPublic(): super(
name: 'IsPublic',
value: true
);
}
```
As you can see, the `Metadata` class requires a `name` and a `value` parameter. The `name` is the name of the metadata, and the `value` is the value of the metadata. You can use any type of value you want.
Also, since Serinus uses a `Context` to store the request information, you can access it using a ContextualizedMetadata.
```dart
import 'package:serinus/serinus.dart';
class IsPublic extends ContextualizedMetadata {
const IsPublic(): super(
name: 'IsPublic',
value: (context) async => context.query['public'] == 'true'
);
}
```
In this case, the `value` is a function that returns a `Future`. This is useful when you need to access the `RequestContext` to get some information.
## Using Metadata
Now we can use the metadata in our controllers or routes.
If you add a metadata to a controller, it will be applied to all the routes of the controller. If you add a metadata to a route, it will be applied only to that specific route. Pretty cool, right?
```dart
import 'package:serinus/serinus.dart';
class UserController extends Controller {
UserController(): super('/users') {
on(Route.get('/'), getUsers, metadata: [IsPublic()]);
on(Route.get('/'), getUser);
}
Future> getUsers(RequestContext context) async {
final users = await context.use().getUsers();
return users;
}
}
```
In this case, the `IsPublic` metadata will be applied only to the `/users` route. This means that if we have an Hook or a Middleware that checks if the user is authenticated, we can skip it for this route.
## Accessing Metadata
How we can access the metadata? It's really simple.
You can access them using two methods in the `RequestContext` object: `stat` and `canStat`.
The first one will return the metadata if it's present, otherwise it will throw a StateError. The second one will only return if the metadata is present or not.
They can be used in combination in this way:
```dart
import 'package:serinus/serinus.dart';
class UserController extends Controller {
UserController(): super('/users') {
on(Route.get('/'), getUsers, metadata: [IsPublic()]);
on(Route.get('/'), getUser);
}
Future> getUsers(RequestContext context) async {
if (context.canStat('IsPublic')) {
// Do something
}
final users = await context.use().getUsers();
return users;
}
}
```
In this case, we check if the `IsPublic` metadata is present in the route. If it is, we can do something special. Otherwise, we can continue with the normal flow.