adapted from this medium-article for now.
A practical approach to improve my understanding of RESTful APIs and C#.
REST - Representational State Transfer:
- This distributed architecture is used to communicate between clients and a server.
- The API centralizes data which different client applications can access using HTTP.
- Universal Resource Indicators (URIs), HTTP verbs and api end points
/api/point
. - Conceptualized by Roy Fielding in 2000
Characteristics of REST Architecture:
- Uniform Interface
- Stateless
- Client Server
- Cashable
- Layered System
Our goal is to build a REST API using ASP.NET Core framework
- Entity Framework Core
- AutoMapper
- Resource
In .NET 6, they unified Startup.cs
and Program.cs
into one Program.cs.
Now registering middleware, services and adding DbContext and everything else into the Program.cs
file.
An ASP.NET Core application consists of a group of middlewares (small pieces of the application attached to the application pipeline, that handle requests and responses) configured in the Startup class
Let’s write a fictional web API for a supermarket. Let’s imagine we have to implement the following scope:
Create a RESTful service that allows client applications to manage the supermarket’s product catalog. It needs to expose endpoints to create, read, edit and delete products categories, such as dairy products and cosmetics, and also to manage products of these categories. For categories, we need to store their names. For products, we need to store their names, unit of measurement (for example, KG for products measured by weight), quantity in the package (for example, 10 if the product is a pack of biscuits) and their respective categories.
classDiagram
Person <|-- Student
Person <|-- Professor
Person : +String name
Person : +String phoneNumber
Person : +String emailAddress
Person: +purchaseParkingPass()
Address "1" <-- "0..1" Person:lives at
class Student{
+int studentNumber
+int averageMark
+isEligibleToEnrol()
+getSeminarsTaken()
}
class Professor{
+int salary
}
class Address{
+String street
+String city
+String state
+int postalCode
+String country
-validate()
+outputAsLabel()
}
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
stateDiagram
state "Todo" as TODO
state "In Progress" as IP
state "Code Review" as CR
state "Deployed" as DEP
state "In Test" as TST
state "Done" as D
[*] --> TODO
TODO --> IP: started
IP --> CR: in review
CR --> IP: review done
IP --> DEP: ready for deploy
DEP --> TST: deployed
TST --> IP: test failed
TST --> D: test passed
D --> [*]
sequenceDiagram
participant Alice
participant Bob
Alice->John: Hello John, how are you?
loop Healthcheck
John->John: Fight against hypochondria
end
Note right of John: Rational thoughts <br/>prevail...
John-->Alice: Great!
John->Bob: How about you?
Bob-->John: Jolly good!
sequenceDiagram
autonumber
actor C as Customer
participant WS as Web Server
participant WH as Warehouse
participant S as Stripe
C->>WS: Submit Order
activate WS
WS->>WH: Check Stock
WS->>S: Process Payment
WS->>WH: Dispatch Order
WS->>C: Show Success
deactivate WS
Handles HTTP request/responses between services.
Let’s start by writing the domain layer. This layer will have our models classes, the classes that will represent our products and categories, as well as repositories and services interfaces. I’ll explain these last two concepts in a while.
This layer will have our models classes, the classes that will represent our products and categories, as well as repositories and services interfaces.
A service class is not a class that should handle data access.
There is a pattern called Repository Pattern that is used to manage data from databases.
Repository classes encapsulate all logic to handle data access.
These repositories expose methods to list, create, edit and delete objects of a given model, the same way you can manipulate collections.
Internally, these methods talk to the database to perform CRUD operations, isolating the database access from the rest of the application.
This directory is going to have everything we need to access the database, such as repositories implementations.
Context folder AppDbContext class must inherit DbContext, a class EF Core uses to map your models to database tables.
A resource class is a class that contains only basic information that will be exchanged between client applications and API endpoints, generally in form of JSON data, to represent some particular information.
-
- Creating the API
- create the folders structure for the web service
- use the .NET CLI tools to scaffold a basic Web API template
- An ASP.NET Core application consists of a group of middleware
-
- Creating the Domain Models
- This layer will have our models classes, the classes that will represent our products and categories,
- as well as repositories and services interfaces.
- Entity Framework Core, the ORM most ASP.NET Core applications use to persist data into a database, to map the relationship between categories and products.
-
- The Categories API
- Controllers services interface - request/respond
- domain services interface - get data from db
-
- Implementing the Categories Service
- services implementations
- The Categories Repository and the Persistence Layer
-
- The Categories Repository and the Persistence Layer
- return to category service and implement list method from ICategoryRepository interface to return data.
- create a new directory called Persistence
- create a new directory called Contexts
- create class called AppDbContext
- a class EF Core uses to map your models to database tables
- Add a new folder called Repositories
- add a new class called BaseRepository
- create class CategoryRepository
-
- Configuring Dependency Injection
- The ConfigureServices and Configure methods are called at runtime by the framework pipeline to configure how the application should work and which components it must use.
- MVC properties for controllers then accessing the services parameter, to configure our dependency bindings.
-
- Testing the Categories API
dotnet run
- test api end-point
-
- Creating a Category Resource
i am here
Let’s start handling GET requests. First of all, when someone requests data from /api/categories via GET verb, the API needs to return all categories. We can create a category service for this purpose.