Une API simple en .NET (C#) qui expose des opérations CRUD pour une base de données PostgreSQL représentant un "Pokedex". Le code est volontairement écrit pour être lisible par des débutants.
- Framework : .NET (probablement .NET 6/7/8/9 selon le projet)
- Base de données : PostgreSQL (fichier Docker Compose fourni)
- ORM : Entity Framework Core
- Documentation API : Swagger (intégrée)
- .NET SDK installé (ex : 6.0, 7.0 ou 9.0 selon votre SDK local)
- Docker & Docker Compose (pour lancer PostgreSQL facilement)
- (Optionnel) Postman / curl pour tester l'API
Le fichier Docker-Compose.yaml attend les variables suivantes (exportées dans votre shell ou dans un .env placé à la racine) :
POSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_DB
Exemple (.env):
POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_DB=pokedex
- Construisez et lancez les services Docker :
# depuis la racine du projet
docker compose up --build- L'API devrait être exposée (selon
Docker-Compose.yaml) au port indiqué (ex :http://localhost:5191ou via Swagger UI) - Swagger UI est activé dans l'application : ouvrez
http://localhost:5191/swagger(ou l'URL affichée par Docker)
Assurez-vous d'avoir une base PostgreSQL disponible et adaptez la chaîne de connexion dans appsettings.json.
# depuis la racine
dotnet build
dotnet run --project pokedex.csprojINSERT INTO pokemon (pokemon_name, pokemon_type, pokemon_gen, pokemon_can_evolve, pokemon_evolution, pokemon_size, pokemon_weight, pokemon_abilities, created_at)
VALUES
('Bulbizarre', 3, 1, TRUE, 'Herbizarre', 70, 69, '{"ability": "Engrais"}', NOW()),
('Salamèche', 1, 1, TRUE, 'Reptincel', 60, 85, '{"ability": "Brasier"}', NOW()),
('Carapuce', 2, 1, TRUE, 'Carabaffe', 50, 90, '{"ability": "Torrent"}', NOW()),
('Pikachu', 4, 1, TRUE, 'Raichu', 40, 60, '{"ability": "Statik"}', NOW()),
('Évoli', 0, 1, TRUE, 'Aquali', 30, 65, '{"ability": "Adaptabilité"}', NOW());INSERT INTO stats (pokemon_id, pokemon_hp, pokemon_attack, pokemon_defense, pokemon_sp_attack, pokemon_sp_defense, pokemon_speed)
VALUES
(1, 45, 49, 49, 65, 65, 45),
(2, 39, 52, 43, 60, 50, 65),
(3, 44, 48, 65, 50, 64, 43),
(4, 35, 55, 40, 50, 50, 90),
(5, 55, 55, 50, 45, 65, 55);INSERT INTO attack (pokemon_id, pokemon_attack_name, pokemon_attack_damage, pokemon_attack_type)
VALUES
(1, 'Fouet Lianes', 45, 3),
(2, 'Flammèche', 40, 1),
(3, 'Pistolet à O', 40, 2),
(4, 'Éclair', 40, 4),
(5, 'Charge', 40, 0);INSERT INTO weakness (pokemon_id, pokemon_weakness_type, pokemon_weakness_number)
VALUES
(1, 1, 2),
(2, 2, 2),
(3, 3, 2),
(4, 8, 2),
(5, 6, 2);INSERT INTO resistance (pokemon_id, pokemon_resistance_type, pokemon_resistance_number)
VALUES
(1, 2, 2),
(2, 3, 2),
(3, 1, 2),
(4, 4, 2),
(5, 17, 2);INSERT INTO trainer (trainer_name, trainer_age)
VALUES
('Sacha', 10),
('Ondine', 12),
('Pierre', 15),
('Blue', 14),
('Giovanni', 40);INSERT INTO team (team_name)
VALUES
('Team Rocket'),
('Team Magma'),
('Team Aqua'),
('Team Galaxie'),
('Team Plasma');INSERT INTO trainer_team (trainer_id, team_id, "isTeamLeader")
VALUES
(1, 1, FALSE),
(2, 2, TRUE),
(3, 3, TRUE),
(4, 4, FALSE),
(5, 5, TRUE);INSERT INTO trainer_pokemon (trainer_id, pokemon_id, pokemon_nickname, pokemon_level, pokemon_xp, captured_at)
VALUES
(1, 4, 'Pika', 12, 500, NOW()),
(2, 3, 'Tortip', 10, 400, NOW()),
(3, 2, 'Salameche', 15, 900, NOW()),
(4, 5, 'Evo', 8, 200, NOW()),
(5, 1, 'Bulbi', 20, 1200, NOW());INSERT INTO location (location_name)
VALUES
('Argenta'),
('Azuria'),
('Céladopole');
INSERT INTO arena (arena_name, location_id, arena_leader, arena_badge)
VALUES
('Arène Argenta', 1, 3, 'Badge Roche'),
('Arène Azuria', 2, 2, 'Badge Cascade'),
('Arène Céladopole', 3, 4, 'Badge Prisme');- GET /pokemons — liste des pokemons
- GET /pokemons/{id} — détail d'un pokemon
- POST /pokemons — créer un pokemon
- PUT /pokemons/{id} — mettre à jour un pokemon
- DELETE /pokemons/{id} — supprimer un pokemon
Autres ressources CRUD (exemples) :
- /weaknesses
- /resistances
- /attacks
- /stats
- /trainers
- /teams
- /trainer-teams
- /trainer-pokemons
- /locations
- /arenas
Chaque ressource suit des routes REST simples (GET, POST, DELETE ou PUT selon le cas).
Créer un pokemon (JSON):
curl -X POST http://localhost:5191/pokemons \
-H "Content-Type: application/json" \
-d '{"pokemonName":"Pikachu","pokemonType":"electric","pokemonGen":1,"pokemonCanEvolve":true}'Lister les pokemons :
curl http://localhost:5191/pokemonsProgram.cs: configuration et démarrage de l'appAppDbContext.cs: définition des DbSets et configuration EF CoreControllers/: controllers pour chaque table (CRUD)Models/: entités EF Core (une classe par fichier)Models/DTOs/: DTOs séparés pour l'entrée/sortieMigrations/: migrations EF CoreDocker-Compose.yaml: configuration Docker (Postgres + api)
- Les DTOs (Data Transfer Objects) sont utilisés pour séparer les modèles exposés par l'API des entités qui correspondent à la base.
- Les controllers utilisent des opérations simples (
ToListAsync()+foreach) pour rester lisibles sans LINQ complexe. - Swagger est activé : utilisez-le pour explorer et tester l'API.
- Ajouter validation plus stricte (DataAnnotations)
- Ajouter gestion des erreurs centralisée (middleware)
- Ajouter tests unitaires
- Sécuriser l'API (authentification)
Ce projet inclut une configuration d'Identity + JWT dans Program.cs :
ApplicationUser(dansModels/ApplicationUser.cs) étendIdentityUser.- Le
AppDbContexthérite d'IdentityDbContext<ApplicationUser>(tables d'identité gérées par EF Core). - Les paramètres JWT sont lus dans
appsettings.jsondepuis le noeudJWT(ValidAudience, ValidIssuer, secret).
Pour utiliser JWT en local :
- Définissez
JWT:secretdansappsettings.jsonou via variable d'environnementJWT__secret. - Créez un utilisateur (par code ou via un endpoint d'inscription) et générez un access token / refresh token.
Utilisez les commandes EF Core pour gérer les migrations :
dotnet ef migrations add <Name> --project pokedex.csproj
dotnet ef database update --project pokedex.csprojVeillez à ce que la chaîne de connexion (ConnectionStrings:DefaultConnection) pointe vers votre instance PostgreSQL.
Un fichier .env.example est fourni. Copiez-le en .env et adaptez les valeurs pour Docker Compose ou votre environnement local.