Compare commits

..

21 Commits
API2 ... master

Author SHA1 Message Date
Nathan BOILEAU 7e37acd37f Fix: error drone
continuous-integration/drone/push Build is passing Details
2 years ago
Nathan BOILEAU dd0d2a661a Merge branch 'linkDB_API'
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 11fe1c243f Petite modif
continuous-integration/drone/push Build is passing Details
2 years ago
Nathan BOILEAU 149a74ffa1 Correction orthographe
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 39193ed5ac 🎨 READ ME + Remove files
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 1a9d159d64 Merge branch 'master' of https://codefirst.iut.uca.fr/git/bastien.ollier/LOL
continuous-integration/drone/push Build is passing Details
2 years ago
Nathan BOILEAU b7e657d883 📝 Ajoute diagramme d'architecture
2 years ago
Nathan BOILEAU ed9293609f Mise à jour de '.drone.yml'
continuous-integration/drone/push Build is passing Details
2 years ago
Nathan BOILEAU b1752c3461 Merge branch 'linkDB_API'
continuous-integration/drone/push Build encountered an error Details
2 years ago
Nathan BOILEAU 76de6eccbb Finish link between API and DB
continuous-integration/drone/push Build is passing Details
2 years ago
Nathan BOILEAU 3eabcfa96e Fix: GetChampions, issue on filtrage
continuous-integration/drone/push Build is passing Details
2 years ago
Nathan BOILEAU 481201a7e3 Mise à jour de 'README.md'
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 048001fdb7 ♻️
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU b733e64a3d image README 🎉
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 27324c0dbb Mise à jour de 'README.md'
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU f48746ef86 rename folder
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 4aecbf62f5 add: Image for readme :tada
continuous-integration/drone/push Build is failing Details
2 years ago
Nathan BOILEAU 9e7a8eb789 Mise à jour de 'README.md'
continuous-integration/drone/push Build is failing Details
2 years ago
Bastien OLLIER 873322d140 Ajouter 'Sources/apiLOL/Dockerfile'
continuous-integration/drone/push Build is failing Details
2 years ago
Bastien OLLIER ea94827f83 Mise à jour de '.drone.yml'
continuous-integration/drone/push Build is failing Details
2 years ago
Bastien OLLIER ced544f2d5 Mise à jour de '.drone.yml'
continuous-integration/drone/push Build is failing Details
2 years ago

@ -39,6 +39,11 @@ steps:
COMMAND: create
OVERWRITE: true
username:
from_secret: SECRET_REGISTRY_USERNAME
password:
from_secret: SECRET_REGISTRY_PASSWORD
- name: tests
image: mcr.microsoft.com/dotnet/sdk:6.0
commands:

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

@ -1,168 +1,85 @@
# prepaLoL
## Diagramme de classes du modèle
```mermaid
classDiagram
class LargeImage{
+/Base64 : string
}
class Champion{
+/Name : string
+/Bio : string
+/Icon : string
+/Characteristics : Dictionary~string, int~
~ AddSkin(skin : Skin) bool
~ RemoveSkin(skin: Skin) bool
+ AddSkill(skill: Skill) bool
+ RemoveSkill(skill: Skill) bool
+ AddCharacteristics(someCharacteristics : params Tuple~string, int~[])
+ RemoveCharacteristics(label : string) bool
+ this~label : string~ : int?
}
Champion --> "1" LargeImage : Image
class ChampionClass{
<<enumeration>>
Unknown,
Assassin,
Fighter,
Mage,
Marksman,
Support,
Tank,
}
Champion --> "1" ChampionClass : Class
class Skin{
+/Name : string
+/Description : string
+/Icon : string
+/Price : float
}
Skin --> "1" LargeImage : Image
Champion "1" -- "*" Skin
class Skill{
+/Name : string
+/Description : string
}
class SkillType{
<<enumeration>>
Unknown,
Basic,
Passive,
Ultimate,
}
Skill --> "1" SkillType : Type
Champion --> "*" Skill
class Rune{
+/Name : string
+/Description : string
}
Rune --> "1" LargeImage : Image
class RuneFamily{
<<enumeration>>
Unknown,
Precision,
Domination
}
Rune --> "1" RuneFamily : Family
class Category{
<<enumeration>>
Major,
Minor1,
Minor2,
Minor3,
OtherMinor1,
OtherMinor2
}
class RunePage{
+/Name : string
+/this[category : Category] : Rune?
- CheckRunes(newRuneCategory : Category)
- CheckFamilies(cat1 : Category, cat2 : Category) bool?
- UpdateMajorFamily(minor : Category, expectedValue : bool)
}
RunePage --> "*" Rune : Dictionary~Category,Rune~
```
## Diagramme de classes des interfaces de gestion de l'accès aux données
```mermaid
classDiagram
direction LR;
class IGenericDataManager~T~{
<<interface>>
GetNbItems() Task~int~
GetItems(index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~T~~
GetNbItemsByName(substring : string)
GetItemsByName(substring : string, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~T~~
UpdateItem(oldItem : T, newItem : T) Task~T~~
AddItem(item : T) Task~T~
DeleteItem(item : T) Task~bool~
}
class IChampionsManager{
<<interface>>
GetNbItemsByCharacteristic(charName : string)
GetItemsByCharacteristic(charName : string, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~
GetNbItemsByClass(championClass : ChampionClass)
GetItemsByClass(championClass : ChampionClass, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~
GetNbItemsBySkill(skill : Skill?)
GetItemsBySkill(skill : Skill?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~
GetNbItemsBySkill(skill : string)
GetItemsBySkill(skill : string, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~
GetNbItemsByRunePage(runePage : RunePage?)
GetItemsByRunePage(runePage : RunePage?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~
}
class ISkinsManager{
<<interface>>
GetNbItemsByChampion(champion : Champion?)
GetItemsByChampion(champion : Champion?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Skin?~~
}
class IRunesManager{
<<interface>>
GetNbItemsByFamily(family : RuneFamily)
GetItemsByFamily(family : RuneFamily, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Rune?~~
}
class IRunePagesManager{
<<interface>>
GetNbItemsByRune(rune : Rune?)
GetItemsByRune(rune : Rune?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~RunePage?~~
GetNbItemsByChampion(champion : Champion?)
GetItemsByChampion(champion : Champion?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~RunePage?~~
}
IGenericDataManager~Champion?~ <|.. IChampionsManager : T--Champion?
IGenericDataManager~Skin?~ <|.. ISkinsManager : T--Skin?
IGenericDataManager~Rune?~ <|.. IRunesManager : T--Rune?
IGenericDataManager~RunePage?~ <|.. IRunePagesManager : T--RunePage?
class IDataManager{
<<interface>>
}
IChampionsManager <-- IDataManager : ChampionsMgr
ISkinsManager <-- IDataManager : SkinsMgr
IRunesManager <-- IDataManager : RunesMgr
IRunePagesManager <-- IDataManager : RunePagesMgr
```
## Diagramme de classes simplifié du Stub
```mermaid
classDiagram
direction TB;
IDataManager <|.. StubData
ChampionsManager ..|> IChampionsManager
StubData --> ChampionsManager
RunesManager ..|> IRunesManager
StubData --> RunesManager
RunePagesManager ..|> IRunePagesManager
StubData --> RunePagesManager
SkinsManager ..|> ISkinsManager
StubData --> SkinsManager
StubData --> RunesManager
StubData --> "*" Champion
StubData --> "*" Rune
StubData --> "*" RunePages
StubData --> "*" Skins
```
# Projet d'Entity FrameWork et Consomation et Développement de services sur League Of Legends
Ce projet est un travail universitaire réalisé durant la deuxième année de BUT à Clermont-Ferrand. Il correspond au travail demandé dans le cadre du cours regroupant Entity Framework et Consommation et Developpement de Services.
![League Of Legends](./Docs/imageCodeFirst/frontImageReadMe.jpg)
Explique ce qu'on a fait et ce qu'on a pas fait et pourquoi on a priorisé ca plutot que d'autre
# :zap: Consommation et Développement de services
Voici l'état des différentes tâches liées à la consommation et au développement de services :
> * :white_check_mark: La mise en place de toutes les opérations CRUD est terminée.
> * :white_check_mark: Une API RESTful a été mise en place en respectant les règles de routage et en utilisant les bons codes de statut.
> * :white_check_mark: La version de l'API a été gérée de manière appropriée.
> * :white_check_mark: Les logs ont été implémentés.
> * :construction: Les tests unitaires sont en cours de réalisation.
> * :construction: La création du client MAUI et sa liaison avec l'API sont en cours de réalisation.
> * :white_check_mark: La liaison avec la base de données est opérationnelle.
> * :white_check_mark: Le filtrage et la pagination des données ont été implémentés.
> * :white_check_mark: Le code est de qualité grâce à l'utilisation de SonarQube.
> * :white_check_mark: L'API a été dockerisée et hébergée sur CodeFirst.
> * :construction: Sécurité
`Note : Le client MAUI n'a pas été réalisé par manque de temps. Les tests unitaires et la sécurité sont réalisés au fur et à mesure de l'avancement du projet.`
---
# :zap: Entity Framework :
Voici l'état des différentes tâches liées à Entity Framework :
> * :white_check_mark: **Exercice 1** : Une base de données a été créée avec une table pour les champions, et des requêtes CRUD ont été implémentées, ainsi que du filtrage et de la pagination. Le client console n'a pas été réalisé pour cet exercice par manque de temps.
> * :white_check_mark: **Exercice 2** : Des tests unitaires ont été écrits et une base de données a été simulée à l'aide de SQLiteInMemory.
> * :white_check_mark: **Exercice 3** : Entity Framework a été déployé et les tests ont été effectués via Code#0.
> * :white_check_mark: **Exercice 4**: Les tables pour les runes et les skins ont été implémentées (sans les relations).
> * :white_check_mark: **Exercice 5** : Une relation OneToMany a été établie entre les champions et les skins.
> * :white_check_mark: **Exercice 6** : Une relation ManyToMany a été établie entre les champions, les rune pages et les runes.
> * :construction: **Exercice 7** : Le mapping entre le modèle et l'entité a été réalisé pour améliorer la qualité du code.
> * :construction: **Exercice 8** : La mise en place du pattern UnitOfWork n'a pas pu être implémentée par manque de temps.
---
### Diagramme d'architechture :
![Diagramme d'architechture](./Docs/imageCodeFirst/DiagrammeArchitecture.png)
#### Partie Client :
La partie client qui n'a pas pu être réalisé dans notre cas, est sensée être constituée du client MAUI et du client Console, qui affichent les ressources et testent l'architecture en utilisant le HTTPDataManager pour effectuer des requêtes à l'API et récupérer des données.
#### DataManager :
Le DataManager utilise l'une des extensions mapper pour convertir les objets DTO en Model, et peut être remplacé par EFDataManager ou StubLib.
#### Partie API :
La partie API reçoit les requêtes et renvoie les objets en conséquence, en utilisant l'EFDataManager pour accéder aux données stockées en base de données. La fluent API permet de définir précisément les attributs de la base de données.
#### Entity Framework :
L'EntityFramework est implémenté avec toutes les classes Entity dérivant du modèle, en utilisant OneToMany et ManyToMany de manière dérivée de celle prévue. Les méthodes CRUD sont implémentées grâce à l'utilisation de l'EFDataManager et le Mapper entre entity et model est requis.
#### Déploiement :
Le projet est déployé avec le projet en conteneur, mais le pattern UnitOfWork n'a pas été abordé.
# :tada: Comment lancer le projet
## 1 - Cloner le dépot
Cloner le dépôt Git en utilisant la commande suivante :
git clone https://codefirst.iut.uca.fr/git/bastien.ollier/LOL.git
## 2 - Configurer le démarrage du projet
> Configurer le projet de démarrage en cliquant sur "Projet de démarrage" à gauche de la flèche verte, puis en sélectionnant l'option "apiLOL".
## 3 - Lancement du projet
Le projet est maintenant prêt à être lancé. Vous pouvez commencer à faire des requêtes sur la base de données via l'API.

@ -1,4 +1,5 @@
using Model;
using Microsoft.EntityFrameworkCore;
using Model;
namespace EFLol.DBDataManager
@ -18,18 +19,21 @@ namespace EFLol.DBDataManager
{
private MyDbContext _context;
public EFChampionManager()
{
_context = new MyDbContext();
}
public async Task<Champion?> AddItem(Champion? item)
{
if (item == null)
{
return null;
throw new Exception("Item is null");
}
var addItem = await _context.AddAsync(item);
await _context.SaveChangesAsync();
return addItem.Entity;
// Va chercher les info du context (Context.champions.get)(DbSet) et les map en champion model
// Dans Program.cs de API rajouter un scope (AddScope <IDataManager, EFDataManager>) -> Ca va dire que a chaque fois que j'utilise un IDataManager, il va créer un EFDataManager
_context.Add(item.ChampionToEntity());
_context.SaveChanges();
return item;
}
@ -39,38 +43,62 @@ namespace EFLol.DBDataManager
{
return false;
}
var deletedItem = _context.Remove(item);
await _context.SaveChangesAsync();
return true;
}
private Func<Champion, string, bool> filterByName = (champion, substring) =>
champion.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
var champ = _context.Champions.Select(c => c == item.ChampionToEntity());
public Task<Champion?> UpdateItem(Champion? oldItem, Champion? newItem)
if (champ.Count() < 1)
{
throw new NotImplementedException();
return false;
}
public Task<int> GetNbItems()
{
throw new NotImplementedException();
_context.Champions.Remove(item.ChampionToEntity());
_context.SaveChanges();
return true;
}
public async Task<IEnumerable<Champion?>> GetItems(int index, int count, string? orderingPropertyName = null, bool @descending = false)
public async Task<Champion?> UpdateItem(Champion? oldItem, Champion? newItem)
{
IEnumerable<Champion> champions = _context.Champions.Skip(index * count).Take(count).OrderBy(champion => orderingPropertyName).Select(champion => champion.ChampionToPoco());
return champions;
if (oldItem != null && newItem != null)
{
var champEntity = await _context.Champions.FirstOrDefaultAsync(c => c.Name == oldItem.Name);
if (champEntity == null)
{
throw new Exception("Champion not found in database");
}
champEntity.Bio = newItem.Bio;
_context.SaveChanges();
return champEntity.ChampionToPoco();
}
throw new Exception("Invalid input parameters");
}
public Task<int> GetNbItemsByName(string substring)
public async Task<int> GetNbItems() => _context.Champions.Count();
public async Task<IEnumerable<Champion?>> GetItems(int index, int count, string? orderingPropertyName = null,
bool descending = false)
{
throw new NotImplementedException();
IEnumerable<Champion> champions = _context.Champions.Skip(index * count)
.Take(count)
.OrderBy(champions => orderingPropertyName)
.Select(champions => champions.ChampionToPoco());
return champions;
}
public Task<IEnumerable<Champion?>> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null,
bool @descending = false)
private Func<Champion, string, bool> filterByName = (champion, substring) =>
champion.Name.IndexOf(substring, StringComparison.InvariantCultureIgnoreCase) >= 0;
public Task<IEnumerable<Champion?>> GetItemsByName(string substring, int index, int count,
string? orderingPropertyName = null, bool descending = false)
=> _context.Champions.Select(champion => champion.ChampionToPoco())
.GetItemsWithFilterAndOrdering(champ => filterByName(champ, substring), index, count,
orderingPropertyName, descending);
public Task<int> GetNbItemsByName(string substring)
{
throw new NotImplementedException();
}
@ -81,7 +109,8 @@ namespace EFLol.DBDataManager
throw new NotImplementedException();
}
public Task<IEnumerable<Champion?>> GetItemsByCharacteristic(string charName, int index, int count, string? orderingPropertyName = null,
public Task<IEnumerable<Champion?>> GetItemsByCharacteristic(string charName, int index, int count,
string? orderingPropertyName = null,
bool @descending = false)
{
throw new NotImplementedException();
@ -92,7 +121,8 @@ namespace EFLol.DBDataManager
throw new NotImplementedException();
}
public Task<IEnumerable<Champion?>> GetItemsByClass(ChampionClass championClass, int index, int count, string? orderingPropertyName = null,
public Task<IEnumerable<Champion?>> GetItemsByClass(ChampionClass championClass, int index, int count,
string? orderingPropertyName = null,
bool @descending = false)
{
throw new NotImplementedException();
@ -103,7 +133,8 @@ namespace EFLol.DBDataManager
throw new NotImplementedException();
}
public Task<IEnumerable<Champion?>> GetItemsBySkill(Skill? skill, int index, int count, string? orderingPropertyName = null, bool @descending = false)
public Task<IEnumerable<Champion?>> GetItemsBySkill(Skill? skill, int index, int count,
string? orderingPropertyName = null, bool @descending = false)
{
throw new NotImplementedException();
}
@ -113,7 +144,8 @@ namespace EFLol.DBDataManager
throw new NotImplementedException();
}
public Task<IEnumerable<Champion?>> GetItemsByRunePage(RunePage? runePage, int index, int count, string? orderingPropertyName = null,
public Task<IEnumerable<Champion?>> GetItemsByRunePage(RunePage? runePage, int index, int count,
string? orderingPropertyName = null,
bool @descending = false)
{
throw new NotImplementedException();
@ -124,7 +156,8 @@ namespace EFLol.DBDataManager
throw new NotImplementedException();
}
public Task<IEnumerable<Champion?>> GetItemsBySkill(string skill, int index, int count, string? orderingPropertyName = null, bool @descending = false)
public Task<IEnumerable<Champion?>> GetItemsBySkill(string skill, int index, int count,
string? orderingPropertyName = null, bool @descending = false)
{
throw new NotImplementedException();
}

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFLol.DBDataManager
{
static class ExtensionsDataManager
{
internal static Task<IEnumerable<T?>> GetItemsWithFilterAndOrdering<T>(this IEnumerable<T> collection,
Func<T, bool> filter, int index, int count, string? orderingPropertyName = null, bool descending = false)
{
IEnumerable<T> temp = collection;
temp = temp.Where(item => filter(item));
if (orderingPropertyName != null)
{
var prop = typeof(T).GetProperty(orderingPropertyName!);
if (prop != null)
{
temp = descending
? temp.OrderByDescending(item => prop.GetValue(item))
: temp.OrderBy(item => prop.GetValue(item));
}
}
return Task.FromResult<IEnumerable<T?>>(temp.Skip(index * count).Take(count));
}
internal static Task<int> GetNbItemsWithFilter<T>(this IEnumerable<T> collection, Func<T, bool> filter)
{
return Task.FromResult(collection.Count(item => filter(item)));
}
internal static Task<T?> AddItem<T>(this IList<T> collection, T? item)
{
if (item == null || collection.Contains(item))
{
return Task.FromResult<T?>(default(T));
}
collection.Add(item);
return Task.FromResult<T?>(item);
}
internal static Task<bool> DeleteItem<T>(this IList<T> collection, T? item)
{
if (item == null)
{
return Task.FromResult(false);
}
bool result = collection.Remove(item!);
return Task.FromResult(result);
}
internal static Task<T?> UpdateItem<T>(this IList<T> collection, T? oldItem, T? newItem)
{
if (oldItem == null || newItem == null) return Task.FromResult<T?>(default(T));
if (!collection.Contains(oldItem))
{
return Task.FromResult<T?>(default(T));
}
collection.Remove(oldItem!);
collection.Add(newItem!);
return Task.FromResult<T?>(newItem);
}
}
}

@ -26,7 +26,7 @@ namespace EFLol
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlite("Data Source=loldb.db");
optionsBuilder.UseSqlite("Data Source=../EFLol/loldb.db");
}
}

@ -23,7 +23,7 @@ namespace TestUnitaire
// Act
var nbInListBefore = data.ChampionsMgr.GetNbItems().Result;
var result = await controller.Post(champDTO);
var result = await controller.AddChampion(champDTO);
var nbInListAfter = data.ChampionsMgr.GetNbItems().Result;
// Assert
@ -47,9 +47,9 @@ namespace TestUnitaire
// Act
// Call method POST to add a champion
var result = await controller.Post(champDTO);
var result = await controller.AddChampion(champDTO);
// Call method GET to get the champion
var resultGet = await controller.GetChampion(name);
var resultGet = await controller.GetChampionByName(name);
// Assert
Assert.Equal(name, champDTO.Name);
@ -71,10 +71,10 @@ namespace TestUnitaire
// Act
// Add a champion
var champDTO = new ChampionDTO(name, "Ancienne bio", "icon.png");
var resultPost = await controller.Post(champDTO);
var resultPost = await controller.AddChampion(champDTO);
// Call method PUT to change the bio of a champion
var resultPut = await controller.Put(name, bio);
var resultPut = await controller.UpdateChampion(name, bio);
var champion = (await data.ChampionsMgr.GetItemsByName(name, 0, 1)).First();
var bioOfChampion = champion.Bio;
@ -99,10 +99,10 @@ namespace TestUnitaire
// Act
// Add a champion
var champDTO = new ChampionDTO(name, "Ancienne bio", "icon.png");
var resultPost = await controller.Post(champDTO);
var resultPost = await controller.AddChampion(champDTO);
// Call method DELETE to delete the champion
var resultDelete = await controller.Delete(name);
var resultDelete = await controller.DeleteChampion(name);
// Assert
// Does the type of the result is a OkObjectResult

@ -1,37 +0,0 @@
using apiLOL;
using apiLOL.Controllers;
using Microsoft.AspNetCore.Mvc;
using StubLib;
namespace TestUnitaire
{
public class TestAPILol
{
[Fact]
public void Test1()
{
}
[Fact]
public void TestPostChampion()
{
// Arrange
var data = new StubData();
var controller = new ControllerChampions(new StubData());
var champDTO = new ChampionDTO("Charles", "Charles est un champion de League of Legends");
// Act
var result = controller.Post(champDTO);
data.ChampionsMgr.AddItem(champDTO.ToModel());
var nbItem = data.ChampionsMgr.GetNbItems();
Task<int> nbItemTask = nbItem;
// Assert
Assert.IsType<OkResult>(result);
// Verify that the champions is added to the stub
Assert.Equal(7, nbItemTask.Result);
}
}
}

@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestUnitaire
{
public class TestEFLol
{
public void TestAddIntoDB()
{
// Arrange
ChampionEntity Zeus = new ChampionEntity
{
Name = "Zeus",
Bio = "Zeus is the king of the gods."
};
// Act
using (var context = new ChampionContext())
{
Console.WriteLine("Adding Zeus to the database...");
context.Champions.Add(Zeus);
context.SaveChanges();
}
// Assert
using (var context = new ChampionContext())
{
var champion = context.Champions.FirstOrDefault(c => c.Name == "Zeus");
if (champion == null)
{
Assert.True(false, "Champion not found in database.");
}
Assert.NotNull(champion);
Assert.Equal("Zeus", champion.Name);
Assert.Equal("Zeus is the king of the gods.", champion.Bio);
}
}
public void TestDeleteFromDB()
{
// Act
}
}
}

@ -1,34 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite" Version="7.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\apiLOL\apiLOL.csproj" />
</ItemGroup>
</Project>

@ -14,6 +14,9 @@
<ItemGroup>
<None Remove="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
<ItemGroup>
<None Include="ConsoleTests.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.2" />

@ -2,7 +2,6 @@
using apiLOL.DTO;
using Microsoft.AspNetCore.Mvc;
using Model;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace apiLOL.Controllers
{
@ -25,66 +24,82 @@ namespace apiLOL.Controllers
[HttpGet]
[ProducesResponseType(typeof(ChampionPageDTO), 200)]
public async Task<IActionResult> Get([FromQuery] int index = 0, int count = 10, string? name = "")
public async Task<IActionResult> GetChampions([FromQuery] int index = 0, int count = 10, string? name = "")
{
//FromQuery permet de filtrer dans la collection de champions en fonction du nom
// Possible de faire une classe PageRequest pour gérer les paramètres index et count
_logger.LogInformation($"methode Get de ControllerChampions appelée");
int nbChampions = await _dataManager.GetNbItems();
_logger.LogInformation($"Nombre de champions : {nbChampions}");
var champs = (await _dataManager.GetItems(index, count)).Select(Model => Model.ToDTO());
var champs = (await _dataManager.GetItemsByName(name, index, int.MaxValue))
.Where(champ => string.IsNullOrEmpty(name) || champ.Name.Contains(name, StringComparison.InvariantCultureIgnoreCase))
.Take(count)
.Select(Model => Model.ToDTO());
var page = new ChampionPageDTO
{
Data = champs,
Index = index,
Count = count,
Count = champs.Count(),
TotalCount = nbChampions
};
return Ok(page);
}
[HttpGet]
[Route("{name}")]
[ProducesResponseType(typeof(ChampionDTO), 200)]
public async Task<IActionResult> GetChampion(string name)
public async Task<IActionResult> GetChampionByName(string name)
{
_logger.LogInformation($"methode GetChampion de ControllerChampions appelée avec le paramètre {name}");
try
{
var champs = (await _dataManager.GetItemsByName(name, 0, 1));
var champs = await _dataManager.GetItemsByName(name, 0, 1);
if (champs.Any())
{
return Ok(champs.First().ToDTO());
}
else
{
return NotFound();
}
}
catch (Exception ex)
{
_logger.LogError($"erreur methode Get de ControllerChampions: {ex}");
return BadRequest("erreur de nom de champion");
}
}
[HttpPost]
public async Task<IActionResult> Post(ChampionDTO champDTO)
public async Task<IActionResult> AddChampion(ChampionDTO champDTO)
{
_logger.LogInformation($"methode Post de ControllerChampions appelée avec le paramètre {champDTO.Name}");
try
{
// Check if the champion already exists in the database
var champs = await _dataManager.GetItemsByName(champDTO.Name, 0, 1);
if (champs.Any())
{
return BadRequest("le champion existe deja");
}
Champion tmp = champDTO.ToModel();
Champion champion = await _dataManager.AddItem(tmp);
ChampionDTO dtoChamp = champion.ToDTO();
return CreatedAtAction(nameof(GetChampion), new {name = dtoChamp.Name}, dtoChamp);
return CreatedAtAction(nameof(GetChampionByName), new { name = dtoChamp.Name }, dtoChamp);
}
catch (Exception ex)
{
_logger.LogError($"erreur methode Post de ControllerChampions: {ex}");
return BadRequest("le champion existe deja");
return BadRequest("erreur lors de l'ajout du champion");
}
}
[HttpPut("{name}")]
public async Task<IActionResult> Put(string name, string bio)
public async Task<IActionResult> UpdateChampion(string name, string bio)
{
_logger.LogInformation(
$"methode Put de ControllerChampions appelée avec le paramètre name: {name} et bio: {bio}");
@ -103,7 +118,7 @@ namespace apiLOL.Controllers
}
[HttpDelete("{name}")]
public async Task<IActionResult> Delete(string name)
public async Task<IActionResult> DeleteChampion(string name)
{
_logger.LogInformation($"methode Delete de ControllerChampions appelée avec le paramètre name: {name}");

@ -13,5 +13,9 @@
public string Name { get; set; }
public string Bio { get; set; }
public string Icon { get; set; }
public bool Equals(ChampionDTO other) => other.Name == this.Name && other.Bio == this.Bio && other.Icon == this.Icon;
public string toString() => $"ChampionDTO: {Name} {Bio} {Icon}";
}
}

Loading…
Cancel
Save