Guidelines¶
This tutorial is created to help developers understand and create new controllers and endpoints in the Giraf project.
An endpoint is basically the end of a communication channel. It is this point the API uses to access resources needed to fulfill a request. Any time the API wants to access the database, it happens through endpoints. Each endpoint has its own URL that the API uses when it wants a specific action.
A controller is a collection of endpoints. Each controller is responsible for a limited area of the server/API and contains the endpoints related to said area. All communication is done through 'requests' and 'responses'.
Controller¶
Naming Convention¶
A controller should always be named after the resource it controls, i.e. UserController
if the controller is responsible for handling requests for user data. The reason
for this convention is that the client-side of the REST api extracts the name of
the class that the request involves and issues a request to host/class_name
.
ASP.NET has a neat way of enforcing this name convention, which is annotating the
controller classes with [Route("[controller]")]
as it automatically fetches
the resource-type of the controller, i.e. User in UserController.
Creating New Controllers¶
When creating a new controller, you start by creating a new class deriving from
the Controller
class. The Controller
class provides useful responses that are
used when sending responses to the API.
Here is an example of a controller:
1 2 3 4 5 6 |
|
Before the class declaration are two attributes
[Authorize]
and [Route("v1/[controller]")]
. The [Authorize]
attribute dictates
who has access to the controller and the endpoints. If there is no [Authorize]
,
anyone can access the controller and its endpoints, while if there is a [Authorize]
you have to be logged in to access the controller and the endpoints.
Additionally you can define what roles the logged in user needs to get access like
this [Authorize(Roles = GirafRole.Guardian)]
or if you want more roles to have
access [Authorize(Roles = GirafRole.SuperUser + "," + GirafRole.Department + "," + GirafRole.Guardian)]
.
Typically, you would only use [Authorize]
for controllers as specifying what
roles have access to the controller, like with [Authorize(Roles = GirafRole.SuperUser)]
,
locks all endpoints to the same access level, meaning you can't make some endpoints
accessible only to a guardian while another is accessible only to a superuser.
The [Route("v1/[controller]")]
attribute modifies the URL for endpoints to include
the pre-fix define in the quotation marks. The [controller]
uses the name of the
controller excluding Controller
in this case it would be /v1/Example
.
Endpoint¶
Endpoints are essentially methods in a controller. Like the controller, an endpoint has some special attributes. Here is an example of an endpoint
1 2 3 4 5 6 7 |
|
The [HttpPost("ExampleEndpoint")]
does two thing, it defines the endpoint's URL
with "/ExampleEndpoint"
and describes what type of operation this endpoint executes.
In this case, if the endpoint was a part of ExampleController
from before, the
full URL would be /v1/Example/ExampleEndpoint
. If you have an endpoint where you
do not want to use the URL defined by the controller, you can start with a /
to
ignore the URL defined in [Route]
, using [HttpPost("/NoRoute/ExampleEndpoint")]
would give the URL /NoRoute/ExampleEndpoint
. [HttpPost]
describes what type
of operation the endpoint does. There are 4 types of operation, [HttpPost]
, [HttpGet]
,
[HttpPut]
, [HttpDelete]
. These operations follows CRUD.
For more information on how the api_client
and the web-api
communicates see
Backend Architecture.
The [Authorize]
option works in the same way as the [Authorize]
in controllers.
The main difference is that this only affects this single endpoint.
So if the controller is set to [Authorize]
, but an endpoint needs access from
non-authorized users, this option is given the value [AllowAnonymous]
as seen
in the example below. This overwrites the [Authorize]
option provided by the controller.
If the opposite is the case, and the endpoint needs restricted authorization, the
option can be set to [Authorize]
or something more specific like
[Authorize(Roles = GirafRole.SuperUser + "," + GirafRole.Department + "," + GirafRole.Guardian)]
.
1 2 3 4 5 6 7 |
|
The [ProducesResponseType(StatusCodes.Status200OK)]
is a response the endpoint
can give. This particular response is for success. Typically you would like more
than this to accommodate multiple outcomes. For instance when a user is not found
like in the example below. For a more detailed list of responses please see
this link.
Bellow is an example of how to use [ProducesResponseType()]
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
You can also use StatusCode(StatusCodes.Status200OK, objectToReturn)
for giving
status codes to a response. The first attribute is a static class containing http
status codes and the second attribute is the object to return.