Skip to content

Commit

Permalink
CODE RUB: Update Numering on Sections
Browse files Browse the repository at this point in the history
  • Loading branch information
hassanhabib authored Jun 9, 2024
1 parent a063c62 commit f7f4535
Showing 1 changed file with 5 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Routes should never have verbs in them. That's the responsibility of the http ve
The Standard also enforces the single-noun principle. Routes should not combine mulitple nouns. For instance, instead of saying: `api/studentsubmissions` we should say: `api/student-submissions`.
On that same line, retreiving submissions for a particular student can be represented as follows: `api/students/{studentId}/submissions` the breakdown here is necessary to imply the intersection between resources compared to pulling everything in storage.

##### 3.1.1.2.0.2.0 Controller Routes
##### 3.1.1.2.0.2.1 Controller Routes
The controller class in a simple ASP.NET application can be set at the top of the controller class declaration with a decoration as follows:

```csharp
Expand All @@ -98,7 +98,7 @@ public class StudentsController

The route there is a template that defines the endpoint to start with `api` and trail by omitting the term "Controller" from the class name. So `StudentsController` would end up being `api/students`. All controllers must have a plural version of the contract they are serving. Unlike services where we say `StudentService`, controllers would be the plural version with `StudentsController`.

##### 3.1.1.2.0.2.1 Routine/Method-Specific Routes
##### 3.1.1.2.0.2.2 Routine/Method-Specific Routes
The same idea applies to methods within the controller class. As the code snippet above says, we decorated `GetStudentByIdAsync` with an `HttpGet` decoration with a particular route identified to append to the existing controller overall route. For instance if the controller route is `api/students`, a routine with `HttpGet("{studentId})` would result in a route that looks like this: `api/students/{studentId}`.

The `studentId` then would be mapped in as an input parameter variable that *must* match the variable defined in the route as follows:
Expand All @@ -121,12 +121,12 @@ public async ValueTask<ActionResult<LibraryCard>> PostLibraryCardAsync(Guid stud
}
```

##### 3.1.1.2.0.2.2 Plural-Singular-Plural
##### 3.1.1.2.0.2.3 Plural-Singular-Plural
When defining routes in a RESTful API, it is important to follow the global naming conventions for these routes. The general rule is to access a collection of resources, then target a particular entity, then again access a collection of resources within that entity, and so on and so forth. For instance, in the library card example above, `api/students/{studentId}/librarycards/{librarycardId}`, we started by accessing all students and then targeting a student with a particular ID. We wanted to access all library cards attached to that student and then target a very particular card by referencing its ID.

That convention works perfectly in one-to-many relationships. But what about one-to-one relationships? Let's assume a student may have one and only one library card at all times. In which case, our route would still look something like this: `api/students/{studentId}/librarycards` with a `POST` verb, and an error would occur as `CONFLICT` if a card is already in place regardless of whether the Ids match or not.

##### 3.1.1.2.0.2.2 Query Parameters & OData
##### 3.1.1.2.0.2.4 Query Parameters & OData
But the route I recommend is the flat-model route. Where every resource lives on its own with its unique routes, in our case here, pulling a library card for a particular student would be as follows: `api/librarycards?studentId={studentId}` or use slightly advanced global technology such as OData where the query would be `api/librarycards?$filter=studentId eq '123'`.

Here's an example of implementing basic query parameters:
Expand All @@ -152,7 +152,7 @@ public async ValueTask<IQueryable<LibraryCard>> GetAllLibraryCards()

The same idea applies to `POST` for a model. Instead of posting towards: `api/students/{studentId}/librarycards` - we can leverage the contract itself to post against `api/librarycards` with a model that contains the student id within. This flat-route idea can simplify the implementation and aligns perfectly with the overall theme of The Standard. We are keeping things simple.

##### 3.1.1.2.0.2.3 X-WWW-Form-UrlEncoded Parameters
##### 3.1.1.2.0.2.5 X-WWW-Form-UrlEncoded Parameters
The Standard enfornces the concept of single-entity. For instance, we can't have a method as follows in a Standard-compliant system:
```csharp
ValueTask<Teacher> GetTeachersByStudentAsync(Student student);
Expand Down

0 comments on commit f7f4535

Please sign in to comment.