Logs_Version_Filtrage_Pagination #5

Merged
emre.kartal merged 10 commits from Logs_Version_Filtrage_Pagination into master 2 years ago

@ -46,6 +46,7 @@ steps:
from_secret: SECRET_SONAR_LOGIN
depends_on: [tests]
# docker image build
- name: docker-build-and-push
image: plugins/docker
settings:
@ -57,6 +58,17 @@ steps:
from_secret: SECRET_REGISTRY_USERNAME
password:
from_secret: SECRET_REGISTRY_PASSWORD
# container deployment
- name: deploy-container
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
environment:
IMAGENAME: hub.codefirst.iut.uca.fr/emre.kartal/lolproject:latest
CONTAINERNAME: lolApi
COMMAND: create
OVERWRITE: true
depends_on: [ docker-build-and-push ]
- name: generate-and-deploy-docs
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-docdeployer
failure: ignore

Binary file not shown.

Binary file not shown.

@ -5,12 +5,12 @@
</div>
**Thème du projet** : Réalisation d'une API et d'un ORM(Entity Framework) qui seront reliés à une base de données dans le thème de League of Legends <img src="https://logo-marque.com/wp-content/uploads/2020/11/League-of-Legends-Embleme.png" width="40" >
**Thème du projet** : Réalisation d'une API et d'un ORM (Entity Framework) qui seront reliés à une base de données dans le thème de League of Legends <img src="https://logo-marque.com/wp-content/uploads/2020/11/League-of-Legends-Embleme.png" width="40" >
</br>
<img src="doc/Images/Title-Répartition.png" width="400">
La racine de notre gitlab est composée de deux dossiers essentiels au projet:
La racine de mon GitLab contient deux dossiers essentiels pour le projet :
[**src**](src) : **Toute la partie codage de l'application**
@ -23,7 +23,7 @@ La racine de notre gitlab est composée de deux dossiers essentiels au projet:
- ### Comment récupérer le projet ?
Tout d'abord si ce n'est pas fait cloner le dépôt de la branche **master/main**, pour cela copier le lien URL du dépôt git :
Tout d'abord, si ce n'est pas déjà fait, clonez le dépôt de la branche **master/main**. Pour ce faire, copiez le lien URL du dépôt git :
<div align = center>
@ -31,7 +31,7 @@ Tout d'abord si ce n'est pas fait cloner le dépôt de la branche **master/main*
</div>
Vous pouvez le cloner via un terminal dans le répertoire que vous souhaitez en tapant la commande : **git clone https://codefirst.iut.uca.fr/git/emre.kartal/LolProject.git** ou utiliser Visual Studio et cloner en entrant le lien :
Vous pouvez le cloner via un terminal dans le répertoire de votre choix en utilisant la commande : **git clone https://codefirst.iut.uca.fr/git/emre.kartal/LolProject.git**. Sinon, vous pouvez utiliser Visual Studio et cloner le dépôt en entrant le lien :
<div align = center>
@ -39,16 +39,31 @@ Vous pouvez le cloner via un terminal dans le répertoire que vous souhaitez en
</div>
:information_source: *Si vous ne disposez pas de Visual Studio, allé sur le site [Microsoft Visual Studio](https://visualstudio.microsoft.com/fr/downloads/) pour pouvoir le télécharger !!!*
:information_source: *Si vous ne disposez pas de Visual Studio, allez sur le site [Microsoft Visual Studio](https://visualstudio.microsoft.com/fr/downloads/) pour pouvoir le télécharger !!!*
- ### Comment lancer l'API dotnet ?
Pour pouvoir utiliser toutes les requêtes de l'API, il est nécessaire de récupérer le projet si cela n'a pas été fait, puis de le lancer à partir de Visual Studio. Vous pouvez directement cliquer sur la solution du projet. Ensuite, dans les projets de démarrage, choisissez "Api-Lol" :
<div align = center>
![Lancer l'API](doc/Images/Api_Launcher.png)
</div>
Normalement, tout est bon et vous serez redirigé vers Swagger, qui est l'interface graphique permettant d'effectuer facilement des requêtes. Il vous suffit ensuite de choisir la version en haut à droite. La version 3.0 est normalement la plus récente et la plus performante en termes de gestion d'erreur :
<div align = center>
![Version API](doc/Images/Swagger_Version.png)
</div>
- ### Comment lancer Le projet Entity Framework ?
Afin de générer les migrations et les tables.
<br>
Vous devez avoir installé correctement EntityFrameworkCore, pour cela il existe la commande : **dotnet tool install --global dotnet-ef** qui peut être lancé à partir d'un terminal, si il est déjà installer mais n'a pas la bonne version : **dotnet tool update --global dotnet-ef** (oui y que le *install* qui change vous êtes perspicace)!
Afin de générer les migrations et les tables, vous devez avoir installé correctement EntityFrameworkCore. Pour cela il existe la commande : **dotnet tool install --global dotnet-ef**, qui peut être lancé à partir d'un terminal. Si elle est déjà installée mais n'a pas la bonne version : **dotnet tool update --global dotnet-ef** (oui, il n'y a que l'*install* qui change. Vous êtes perspicace !).
Aussi assurer vous d'avoir installé sur Visual Studio au préalable les package Nuget suivants :
Assurez-vous également d'avoir installé les packages Nuget suivants sur Visual Studio au préalable :
<div align = center>
@ -56,13 +71,13 @@ Aussi assurer vous d'avoir installé sur Visual Studio au préalable les package
</div>
Ensuite sur le terminal PowerShell ou Visual Studio, lancer la migration via la commande : **dotnet ef migrations add monNomDeMigration** (n'oublier pas de vous situer dans le dossier "/MyFlib" lorsque vous l'exécuter)!
Ensuite, sur le terminal PowerShell ou Visual Studio, lancer la migration via la commande : **dotnet ef migrations add monNomDeMigration** (n'oubliez pas de vous situer dans le dossier "/MyFlib" lorsque vous l'exécutez)!
- ### Comment voir la base de données ?
C'est bien beau toutes ces étapes mais sil n'y a pas de résultat à quoi cela sert !
C'est bien beau toutes ces étapes, mais sil n'y a pas de résultat, à quoi cela sert !
Tout d'abord veuillez regarder dans l'onglet extension, si l'outil **SQLite and SQL Server Compact Toolbax** est bien installé.
Tout d'abord, veuillez regarder dans l'onglet Extensions si l'outil **SQLite and SQL Server Compact Toolbax** est bien installé.
Puis, afin de visualiser la migration dans la base de données, cliquer dans l'onglet **Outils**->**SQLLite/ SQL Server compact Toolbox** :
@ -72,7 +87,7 @@ Puis, afin de visualiser la migration dans la base de données, cliquer dans l'o
</div>
Et enfin cliquer sur l'icône ci-dessous pour faire la connexion à la solution courent :
Et enfin cliquez sur l'icône ci-dessous pour établir la connexion à la solution en cours :
<div align = center>
@ -80,14 +95,14 @@ Et enfin cliquer sur l'icône ci-dessous pour faire la connexion à la solution
</div>
Vous pouvez dorénavant voir toutes les tables qui y sont enregistrées ! Si vous souhaitez ajouter des modifications à la base de données et les visualiser,
réaliser à nouveau la migration (ou *updater* celui actuel), puis supprimer toutes les tables et lancer la commande : **dotnet ef database update** et enfin rafraichissez la BD !
Vous pouvez désormais voir toutes les tables qui y sont enregistrées ! Si vous souhaitez ajouter des modifications à la base de données et les visualiser,
réalisez à nouveau la migration (ou mettez à jour celle actuelle), puis supprimez toutes les tables et lancez la commande : **dotnet ef database update** et enfin rafraîchissez la base de données !
:information_source: *Notez qu'il est également possible grâce à SQLLite d'ajouter, modifier ou supprimer des données dans les tables.*
:information_source: *Notez qu'il est également possible, grâce à SQLLite, d'ajouter, modifier ou supprimer des données dans les tables.*
<img src="doc/Images/Title-Environnement.png" width="400" >
Mon environnement de travail se base sur un outil et un langage en particulier :👇
Mon environnement de travail est basé sur un outil et un langage en particulier : 👇
<div align = center>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

@ -9,6 +9,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.2" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.15.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />

@ -1,75 +0,0 @@
using ApiLol.Mapper;
using DTO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Model;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ApiLol.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ChampionsController : ControllerBase
{
private readonly IDataManager _manager;
public ChampionsController(IDataManager dataManager)
{
this._manager = dataManager;
}
// GET: api/<ValuesController>
[HttpGet]
public async Task<IActionResult> Get()
{
IEnumerable<ChampionDto> dtos = (await _manager.ChampionsMgr.GetItems(0, await _manager.ChampionsMgr.GetNbItems()))
.Select(x => x.ToDto());
return Ok(dtos);
}
// GET api/<ValuesController>/5
[HttpGet("{name}")]
public async Task<IActionResult> Get(string name)
{
var dtos = (await _manager.ChampionsMgr.GetItemsByName(name,0, await _manager.ChampionsMgr.GetNbItems()))
.Select(x => x.ToDto());
if(dtos.IsNullOrEmpty())
{
return NotFound();
}
return Ok(dtos);
}
// POST api/<ValuesController>
[HttpPost]
public async Task<IActionResult> Post([FromBody] ChampionDto champion)
{
return CreatedAtAction(nameof(Get),
(await _manager.ChampionsMgr.AddItem(champion.ToModel())).ToDto());
}
// PUT api/<ValuesController>/5
[HttpPut("{name}")]
public async Task<IActionResult> Put(string name, [FromBody] ChampionDto champion)
{
var dtos = (await _manager.ChampionsMgr.GetItemsByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
if(dtos.IsNullOrEmpty())
{
return BadRequest();
}
return Ok(await _manager.ChampionsMgr.UpdateItem(dtos.First(), champion.ToModel()));
}
// DELETE api/<ValuesController>/5
[HttpDelete("{name}")]
public async Task<IActionResult> Delete(string name)
{
var dtos = (await _manager.ChampionsMgr.GetItemsByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
if (dtos.IsNullOrEmpty())
{
return BadRequest();
}
return Ok(await _manager.ChampionsMgr.DeleteItem(dtos.First()));
}
}
}

@ -0,0 +1,76 @@
using ApiLol.Mapper;
using 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
{
[Route("api/[controller]")]
[ApiController]
public class SkinsController : ControllerBase
{
private readonly IDataManager _manager;
private readonly ILogger<SkinsController> _logger;
public SkinsController(IDataManager dataManager, ILogger<SkinsController> logger)
{
_logger = logger;
this._manager = dataManager;
}
// GET: api/<SkinsController>
[HttpGet]
public async Task<IActionResult> Get([FromQuery] PageRequest pageRequest)
{
try
{
int nbTotal = await _manager.ChampionsMgr.GetNbItems();
if (pageRequest.count + pageRequest.index > nbTotal)
{
_logger.LogWarning($"too many, maximum {nbTotal}");
return BadRequest($"Champion limit exceed, max {nbTotal}");
}
_logger.LogInformation($"method Get call");
IEnumerable<SkinDtoC> dtos = (await _manager.SkinsMgr.GetItems(pageRequest.index, pageRequest.count))
.Select(x => x.ToDtoC());
return Ok(dtos);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
}
// GET api/<SkinsController>/5
[HttpGet("{name}")]
public async Task<IActionResult> Get(string name)
{
return Ok();
}
// POST api/<SkinsController>
[HttpPost]
public async Task<IActionResult> Post([FromBody] string value)
{
return Ok();
}
// PUT api/<SkinsController>/5
[HttpPut("{name}")]
public async Task<IActionResult> Put(int id, [FromBody] string value)
{
return Ok();
}
// DELETE api/<SkinsController>/5
[HttpDelete("{name}")]
public async Task<IActionResult> Delete(string name)
{
return Ok();
}
}
}

@ -0,0 +1,82 @@
using ApiLol.Mapper;
using DTO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Model;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ApiLol.Controllers.v1
{
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ChampionsController : ControllerBase
{
private readonly IDataManager _manager;
private readonly ILogger<ChampionsController> _logger;
public ChampionsController(IDataManager dataManager, ILogger<ChampionsController> logger)
{
_logger = logger;
this._manager = dataManager;
}
// GET: api/<ValuesController>
[HttpGet]
public async Task<IActionResult> Get([FromQuery] PageRequest pageRequest)
{
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), pageRequest);
IEnumerable<ChampionDto> dtos = (await _manager.ChampionsMgr.GetItems(pageRequest.index, pageRequest.count, pageRequest.orderingPropertyName, pageRequest.descending))
.Select(x => x.ToDto());
return Ok(dtos);
}
// GET api/<ValuesController>/5
[HttpGet("{name}")]
public async Task<IActionResult> Get(string name)
{
_logger.LogInformation("method {Action} call with {name}", nameof(Get), name);
var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()))
.Select(x => x.ToDto());
return Ok(dtos.First());
}
// POST api/<ValuesController>
[HttpPost]
public async Task<IActionResult> Post([FromBody] ChampionDto champion)
{
_logger.LogInformation("method {Action} call with {item}", nameof(Post), champion);
return CreatedAtAction(nameof(Get),
(await _manager.ChampionsMgr.AddItem(champion.ToModel())).ToDto());
}
// PUT api/<ValuesController>/5
[HttpPut("{name}")]
public async Task<IActionResult> Put(string name, [FromBody] ChampionDto champion)
{
_logger.LogInformation("method {Action} call with {name} and {item}", nameof(Put), name, champion);
var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
return Ok((await _manager.ChampionsMgr.UpdateItem(dtos.First(), champion.ToModel())).ToDto());
}
// DELETE api/<ValuesController>/5
[HttpDelete("{name}")]
public async Task<IActionResult> Delete(string name)
{
_logger.LogInformation("method {Action} call with {name}", nameof(Delete), name);
var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
return Ok(await _manager.ChampionsMgr.DeleteItem(dtos.First()));
}
}
}

@ -0,0 +1,211 @@
using ApiLol.Mapper;
using Azure.Core;
using DTO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Model;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ApiLol.Controllers.v2
{
[ApiVersion("2.0")]
[ApiVersion("3.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ChampionsController : ControllerBase
{
private readonly IDataManager _manager;
private readonly ILogger<ChampionsController> _logger;
public ChampionsController(IDataManager dataManager, ILogger<ChampionsController> logger)
{
_logger = logger;
this._manager = dataManager;
}
// GET: api/<ValuesController>
[HttpGet]
public async Task<IActionResult> Get([FromQuery] PageRequest pageRequest)
{
try
{
int nbTotal = await _manager.ChampionsMgr.GetNbItems();
if (pageRequest.count == 0)
{
pageRequest = new PageRequest() { index = 0, count = nbTotal };
}
else if (pageRequest.count * pageRequest.index >= nbTotal)
{
_logger.LogWarning($"too many, maximum {nbTotal}");
return BadRequest($"Champion limit exceed, max {nbTotal}");
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), pageRequest.count);
IEnumerable<ChampionDto> dtos = (await _manager.ChampionsMgr.GetItems(pageRequest.index, pageRequest.count))
.Select(x => x.ToDto());
return Ok(dtos);
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
// GET: api/<ValuesController>
[HttpGet, MapToApiVersion("3.0")]
public async Task<IActionResult> GetV3([FromQuery] PageRequest pageRequest)
{
try
{
int nbTotal = await _manager.ChampionsMgr.GetNbItems();
if (pageRequest.count == 0)
{
pageRequest = new PageRequest() { index = 0, count = nbTotal };
}
else if (pageRequest.count * pageRequest.index >= nbTotal || pageRequest.count > nbTotal)
{
_logger.LogWarning("too many, maximum {number}", nbTotal);
return BadRequest($"Champion limit exceed, max {nbTotal}");
}
_logger.LogInformation("Executing {Action} with parameters: {Parameters}", nameof(Get), pageRequest);
IEnumerable<ChampionDto> dtos = (await _manager.ChampionsMgr.GetItems(pageRequest.index, pageRequest.count, pageRequest.orderingPropertyName, pageRequest.descending))
.Select(x => x.ToDto());
return Ok(new { Data = dtos, index = pageRequest.index, count = pageRequest.count, total = nbTotal});
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
// GET api/<ValuesController>/5
[HttpGet("{name}")]
public async Task<IActionResult> Get(string name)
{
try
{
_logger.LogInformation("method {Action} call with {name}", nameof(Get), name);
var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()))
.Select(x => x.ToDto());
if (dtos.IsNullOrEmpty())
{
_logger.LogWarning($"{name} was not found");
return NotFound();
}
return Ok(dtos.First());
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
// POST api/<ValuesController>
[HttpPost]
public async Task<IActionResult> Post([FromBody] ChampionDto champion)
{
try
{
_logger.LogInformation("method {Action} call with {item}", nameof(Post), champion);
var dtos = (await _manager.ChampionsMgr.GetItemByName(champion.Name, 0, await _manager.ChampionsMgr.GetNbItems()));
if (!dtos.IsNullOrEmpty())
{
return BadRequest("Name is already exist");
}
return CreatedAtAction(nameof(Get),
(await _manager.ChampionsMgr.AddItem(champion.ToModel())).ToDto());
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
// PUT api/<ValuesController>/5
[HttpPut("{name}")]
public async Task<IActionResult> Put(string name, [FromBody] ChampionDto champion)
{
try
{
_logger.LogInformation("method {Action} call with {name} and {item}", nameof(Put), name, champion);
var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
if (dtos.IsNullOrEmpty())
{
return NotFound($"Name {name} not exist");
}
// Checks if the new name exists
if (name != champion.Name)
{
var dtos2 = (await _manager.ChampionsMgr.GetItemByName(champion.Name, 0, await _manager.ChampionsMgr.GetNbItems()));
if (dtos2.IsNullOrEmpty() || dtos2.Count() > 0)
{
return BadRequest("Name is already exist");
}
}
return Ok((await _manager.ChampionsMgr.UpdateItem(dtos.First(), champion.ToModel())).ToDto());
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
[HttpGet("/{name}/skins")]
public async Task<ActionResult<SkinDto>> GetChampionsSkins(string name)
{
try
{
_logger.LogInformation("method {Action} call with {name}", nameof(GetChampionsSkins), name);
var champions = await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems());
//skinsDTO
IEnumerable<SkinDto> res = champions.First().Skins.Select(e => e.ToDto());
return Ok(res);
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
[HttpGet("/{name}/skills")]
public async Task<ActionResult<SkillDto>> GetChampionsSkills(string name)
{
try
{
_logger.LogInformation("method {Action} call with {name}", nameof(GetChampionsSkills), name);
var champions = await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems());
//SkillDTO
IEnumerable<SkillDto> res = champions.First().Skills.Select(e => e.ToDto());
return Ok(res);
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
// DELETE api/<ValuesController>/5
[HttpDelete("{name}")]
public async Task<IActionResult> Delete(string name)
{
try
{
_logger.LogInformation("method {Action} call with {name}", nameof(Delete), name);
var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
if (dtos.IsNullOrEmpty())
{
_logger.LogWarning("{name} was not found", name);
return BadRequest();
}
return Ok(await _manager.ChampionsMgr.DeleteItem(dtos.First()));
}
catch (Exception error)
{
return BadRequest(error.Message);
}
}
}
}

@ -13,13 +13,20 @@ namespace ApiLol.Mapper
Bio = champion.Bio,
Class = champion.Class.ToDto(),
Icon = champion.Icon,
Image = champion.Image.Base64
Image = champion.Image.ToDto(),
Skins = champion.Skins.Select(e => e.ToDto()),
Skills = champion.Skills.Select(e => e.ToDto())
};
}
public static Champion ToModel(this ChampionDto championDto)
{
return new Champion(championDto.Name, championDto.Class.ToModel(), championDto.Icon, championDto.Image,championDto.Bio);
var champ = new Champion(championDto.Name, championDto.Class.ToModel(), championDto.Icon, championDto.Image.Base64, championDto.Bio);
foreach(var skin in championDto.Skins)
{
champ.AddSkin(skin.ToModel(champ));
}
return champ;
}
}

@ -0,0 +1,21 @@
using DTO;
using Model;
namespace ApiLol.Mapper
{
public static class LargeImageMapper
{
public static LargeImageDto ToDto(this LargeImage largeImage)
{
return new LargeImageDto()
{
Base64 = largeImage.Base64
};
}
public static LargeImage ToModel(this LargeImageDto largeImageDto)
{
return new LargeImage(largeImageDto.Base64);
}
}
}

@ -14,7 +14,7 @@ namespace ApiLol.Mapper
};
}
/* public static Rune ToModel(this RuneDto rune)
/* public static Rune ToModel(this RuneDto runeDto)
{
return new Rune(rune.Name)
{

@ -11,15 +11,13 @@ namespace ApiLol.Mapper
{
Name = skill.Name,
Description = skill.Description,
Type = skill.Type.ToDto()
};
}
/* public static Skill ToModel(this SkillDto skill)
public static Skill ToModel(this SkillDto skillDto)
{
return new Skill(skill.Name)
{
Description = skill.Description
};
}*/
return new Skill(skillDto.Name, skillDto.Type.ToModel(), skillDto.Description);
}
}
}

@ -1,18 +1,39 @@
using DTO;
using Model;
namespace ApiLol.Mapper
{
public static class SkinMapper
{
public static SkinDto ToDto(this SkinDto skin)
public static SkinDto ToDto(this Skin skin)
{
return new SkinDto()
{
Name = skin.Name,
Description = skin.Description,
Icon = skin.Icon,
Image = skin.Image.ToDto(),
Price = skin.Price
};
}
public static SkinDtoC ToDtoC(this Skin skin)
{
return new SkinDtoC()
{
Name = skin.Name,
Description = skin.Description,
Icon = skin.Icon,
Image = skin.Image.ToDto(),
Price = skin.Price,
ChampionName = skin.Champion.Name
};
}
public static Skin ToModel(this SkinDto skinDto, Champion champ)
{
return new Skin(skinDto.Name, champ, skinDto.Price, skinDto.Icon, skinDto.Image.Base64, skinDto.Description);
}
}
}

@ -9,9 +9,9 @@ namespace ApiLol.Mapper
{
return (ChampionClassDto) championClass;
}
public static ChampionClass ToModel(this ChampionClassDto championClass)
public static ChampionClass ToModel(this ChampionClassDto championClassDto)
{
return (ChampionClass) championClass;
return (ChampionClass) championClassDto;
}
}
}

@ -0,0 +1,57 @@
using DTO;
using Model;
namespace ApiLol.Mapper
{
public static class SkillTypeMapper
{
public static SkillTypeDto ToDto(this SkillType skillType)
{
if (skillType == SkillType.Unknown)
{
return SkillTypeDto.Unknown;
}
if (skillType == SkillType.Basic)
{
return SkillTypeDto.Basic;
}
if (skillType == SkillType.Passive)
{
return SkillTypeDto.Passive;
}
if (skillType == SkillType.Ultimate)
{
return SkillTypeDto.Ultimate;
}
else
{
return SkillTypeDto.Unknown;
}
}
public static SkillType ToModel(this SkillTypeDto skillTypeDto)
{
if (skillTypeDto == SkillTypeDto.Unknown)
{
return SkillType.Unknown;
}
if (skillTypeDto == SkillTypeDto.Basic)
{
return SkillType.Basic;
}
if (skillTypeDto == SkillTypeDto.Passive)
{
return SkillType.Passive;
}
if (skillTypeDto == SkillTypeDto.Ultimate)
{
return SkillType.Ultimate;
}
else
{
return SkillType.Unknown;
}
}
}
}

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Model;
using StubLib;
@ -9,16 +11,41 @@ builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApiVersioning(opt =>
{
opt.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
new HeaderApiVersionReader("x-api-version"),
new MediaTypeApiVersionReader("x-api-version"));
});
// Add ApiExplorer to discover versions
builder.Services.AddVersionedApiExplorer(setup =>
{
setup.GroupNameFormat = "'v'VVV";
setup.SubstituteApiVersionInUrl = true;
});
builder.Services.AddSingleton<IDataManager, StubData>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI(options =>
{
app.UseSwagger();
app.UseSwaggerUI();
}
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
});
app.UseHttpsRedirection();

@ -18,19 +18,19 @@ namespace Client
httpClient.BaseAddress = new Uri("https://localhost:7252;http://localhost:5252");
}
public async Task<IEnumerable<ChampionDto>> GetChampion()
public async Task<IEnumerable<ChampionDto>> GetChampion(int index, int count)
{
var champions = await _httpClient.GetFromJsonAsync<IEnumerable<ChampionDto>>(ApiChampions);
return champions;
var url = $"{ApiChampions}?index={index}&count={count}";
return await _httpClient.GetFromJsonAsync<IEnumerable<ChampionDto>>(url);
}
public async void Add(ChampionDto champion)
/* public async void Add(ChampionDto champion)
{
await _httpClient.PostAsJsonAsync<ChampionDto>(ApiChampions, champion);
}
}*/
/* public async void Delete(ChampionDto champion)
{
await _httpClient.DeleteAsync(champion);
await _httpClient.DeleteAsync(champion.Name);
}
public async void Update(ChampionDto champion)

@ -1,2 +1,38 @@
// See https://aka.ms/new-console-template for more information
using Client;
using DTO;
Console.WriteLine("Hello, World!");
var championClient = new ChampionHttpClient(new HttpClient());
// Get all champions
var champions = await championClient.GetChampion(0,6);
Console.WriteLine("All champions:");
foreach (var champion in champions)
{
Console.WriteLine($"{champion.Name} ({champion.Bio})");
}
/*// Add a new champion
var newChampion = new ChampionDto { Name = "Akali", Role = "Assassin" };
championClient.Add(newChampion);
// Delete a champion
var championToDelete = champions.FirstOrDefault(c => c.Name == "Riven");
if (championToDelete != null)
{
championClient.Delete(championToDelete);
Console.WriteLine($"{championToDelete.Name} deleted.");
}
// Update a champion
var championToUpdate = champions.FirstOrDefault(c => c.Name == "Ashe");
if (championToUpdate != null)
{
championToUpdate.Role = "Marksman";
championClient.Update(championToUpdate);
Console.WriteLine($"{championToUpdate.Name} updated.");
}
*/

@ -6,8 +6,9 @@
public string Bio { get; set; }
public ChampionClassDto Class { get; set; }
public string Icon { get; set; }
public string Image { get; set; }
public LargeImageDto Image { get; set; }
public IEnumerable<SkinDto> Skins { get; set; }
public IEnumerable<SkillDto> Skills { get; set; }
}
}

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTO
{
public class LargeImageDto
{
public string Base64 { get; set; }
}
}

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTO
{
public class PageRequest
{
public int index { get; set; } = 0;
public int count { get; set; } = 0;
public string? orderingPropertyName { get; set; } = "Name";
public bool descending { get; set; } = false;
}
}

@ -1,4 +1,5 @@
using System;
using DTO.enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -10,6 +11,8 @@ namespace DTO
{
public string Name { get; set; }
public string Description { get; set; }
public RuneFamilyDto Family { get; set; }
public LargeImageDto Image { get; set; }
}
}

@ -10,5 +10,6 @@ namespace DTO
{
public string Name { get; set; }
public string Description { get; set; }
public SkillTypeDto Type { get; set; }
}
}

@ -11,6 +11,7 @@ namespace DTO
public string Name { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
public LargeImageDto Image { get; set; }
public float Price { get; set; }
}

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTO
{
public class SkinDtoC
{
public string Name { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
public LargeImageDto Image { get; set; }
public float Price { get; set; }
public string ChampionName { get; set; }
}
}

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTO.enums
{
public enum RuneFamilyDto
{
Unknown,
Precision,
Domination
}
}

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DTO
{
public enum SkillTypeDto
{
Unknown,
Basic,
Passive,
Ultimate
}
}

@ -62,7 +62,7 @@ public class Champion : IEquatable<Champion>
public ImmutableHashSet<Skill> Skills => skills.ToImmutableHashSet();
private HashSet<Skill> skills = new HashSet<Skill>();
internal bool AddSkin(Skin skin)
public bool AddSkin(Skin skin)
{
if (skins.Contains(skin))
return false;
@ -70,7 +70,7 @@ public class Champion : IEquatable<Champion>
return true;
}
internal bool RemoveSkin(Skin skin)
public bool RemoveSkin(Skin skin)
=> skins.Remove(skin);
public bool AddSkill(Skill skill)

@ -5,7 +5,8 @@ public interface IGenericDataManager<T>
Task<IEnumerable<T>> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false);
Task<int> GetNbItemsByName(string substring);
Task<IEnumerable<T>> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false);
Task<T> UpdateItem(T oldItem, T newItem);
Task<IEnumerable<T>> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false);
Task<T> UpdateItem(T oldItem, T newItem);
Task<T> AddItem(T item);
Task<bool> DeleteItem(T item);
}

@ -3,19 +3,19 @@ using Model;
namespace StubLib
{
public partial class StubData
{
private List<Champion> champions = new()
{
new Champion("Akali", ChampionClass.Assassin),
new Champion("Aatrox", ChampionClass.Fighter),
new Champion("Ahri", ChampionClass.Mage),
new Champion("Akshan", ChampionClass.Marksman),
new Champion("Bard", ChampionClass.Support),
new Champion("Alistar", ChampionClass.Tank),
};
public class ChampionsManager : IChampionsManager
public partial class StubData
{
private List<Champion> champions = new()
{
new Champion("Akali", ChampionClass.Assassin),
new Champion("Aatrox", ChampionClass.Fighter),
new Champion("Ahri", ChampionClass.Mage),
new Champion("Akshan", ChampionClass.Marksman),
new Champion("Bard", ChampionClass.Support),
new Champion("Alistar", ChampionClass.Tank),
};
public class ChampionsManager : IChampionsManager
{
private readonly StubData parent;
@ -82,19 +82,24 @@ namespace StubLib
(parent.championsAndRunePages
.Where(tuple => tuple.Item2.Equals(runePage))
.Select(tuple => tuple.Item1)
.Skip(index*count).Take(count));
.Skip(index * count).Take(count));
private Func<Champion, string, bool> filterByName = (champ, substring) => champ.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
private Func<Champion, string, bool> filterByName = (champ, substring) => champ.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
private Func<Champion, string, bool> filterByNameContains = (champ, substring) => champ.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
public Task<int> GetNbItemsByName(string substring)
=> parent.champions.GetNbItemsWithFilter(champ => filterByName(champ, substring));
public Task<IEnumerable<Champion?>> GetItemsByName(string substring, int index, int count, string? orderingPropertyName, bool descending = false)
=> parent.champions.GetItemsWithFilterAndOrdering(champ => filterByNameContains(champ, substring), index, count, orderingPropertyName, descending);
public Task<IEnumerable<Champion?>> GetItemByName(string substring, int index, int count, string? orderingPropertyName, bool descending = false)
=> parent.champions.GetItemsWithFilterAndOrdering(champ => filterByName(champ, substring), index, count, orderingPropertyName, descending);
public Task<Champion?> UpdateItem(Champion? oldItem, Champion? newItem)
=> parent.champions.UpdateItem(oldItem, newItem);
}
}
}
}

@ -27,6 +27,9 @@ namespace StubLib
=> this.parent = parent;
private static Func<RunePage, string, bool> filterByName
= (rp, substring) => rp.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
private static Func<RunePage, string, bool> filterByNameContains
= (rp, substring) => rp.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
private static Func<RunePage, Rune?, bool> filterByRune
@ -51,6 +54,11 @@ namespace StubLib
.Skip(index*count).Take(count));
public Task<IEnumerable<RunePage?>> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.runePages.GetItemsWithFilterAndOrdering(
rp => filterByNameContains(rp, substring),
index, count, orderingPropertyName, descending);
public Task<IEnumerable<RunePage?>> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.runePages.GetItemsWithFilterAndOrdering(
rp => filterByName(rp, substring),
index, count, orderingPropertyName, descending);

@ -37,6 +37,9 @@ namespace StubLib
= (rune, family) => rune.Family == family;
private static Func<Rune, string, bool> filterByName
= (rune, substring) => rune.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
private static Func<Rune, string, bool> filterByNameContains
= (rune, substring) => rune.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
public Task<IEnumerable<Rune?>> GetItemsByFamily(RuneFamily family, int index, int count, string? orderingPropertyName = null, bool descending = false)
@ -45,6 +48,11 @@ namespace StubLib
index, count, orderingPropertyName, descending);
public Task<IEnumerable<Rune?>> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.runes.GetItemsWithFilterAndOrdering(
rune => filterByNameContains(rune, substring),
index, count, orderingPropertyName, descending);
public Task<IEnumerable<Rune?>> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.runes.GetItemsWithFilterAndOrdering(
rune => filterByName(rune, substring),
index, count, orderingPropertyName, descending);

@ -48,7 +48,9 @@ namespace StubLib
private static Func<Skin, Champion?, bool> filterByChampion = (skin, champion) => champion != null && skin.Champion.Equals(champion!);
private static Func<Skin, string, bool> filterByName = (skin, substring) => skin.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
private static Func<Skin, string, bool> filterByName = (skin, substring) => skin.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
private static Func<Skin, string, bool> filterByNameContains = (skin, substring) => skin.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
public Task<IEnumerable<Skin?>> GetItemsByChampion(Champion? champion, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.skins.GetItemsWithFilterAndOrdering(
@ -56,6 +58,11 @@ namespace StubLib
index, count, orderingPropertyName, descending);
public Task<IEnumerable<Skin?>> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.skins.GetItemsWithFilterAndOrdering(
skin => filterByNameContains(skin, substring),
index, count, orderingPropertyName, descending);
public Task<IEnumerable<Skin?>> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
=> parent.skins.GetItemsWithFilterAndOrdering(
skin => filterByName(skin, substring),
index, count, orderingPropertyName, descending);

@ -1,7 +1,9 @@
using ApiLol.Controllers;
using ApiLol.Controllers.v2;
using DTO;
using Microsoft.AspNetCore.Mvc;
using Model;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using StubLib;
namespace ApiTests
@ -14,7 +16,7 @@ namespace ApiTests
public ChampionsControllerTest()
{
stub = new StubData();
champs = new ChampionsController(stub);
champs = new ChampionsController(stub, new NullLogger<ChampionsController>());
}
[TestMethod]
@ -23,7 +25,8 @@ namespace ApiTests
//Arrange
//Act
var champion = await champs.Get();
var total = await stub.ChampionsMgr.GetNbItems();
var champion = await champs.Get(new PageRequest());
//Assert
var objectResult = champion as OkObjectResult;
@ -32,7 +35,7 @@ namespace ApiTests
var champions = objectResult?.Value as IEnumerable<ChampionDto>;
Assert.IsNotNull(champions);
Assert.AreEqual(champions.Count(), await stub.ChampionsMgr.GetNbItems());
Assert.AreEqual(champions.Count(), total);
}
@ -43,7 +46,11 @@ namespace ApiTests
var ChampionDto = new ChampionDto
{
Name = "Sylas",
Bio = "Good"
Bio = "Good",
Class = ChampionClassDto.Tank,
Icon = "",
Image = new LargeImageDto() { Base64 = "" },
Skins = new List<SkinDto>()
};
//Act
@ -58,5 +65,63 @@ namespace ApiTests
}
[TestMethod]
public async Task TestPutChampion()
{
//Arange
var ChampionDto = new ChampionDto
{
Name = "Sylas",
Bio = "Good",
Class = ChampionClassDto.Tank,
Icon = "",
Image = new LargeImageDto() { Base64 = "" },
Skins = new List<SkinDto>()
};
var ChampionDtoPut = new ChampionDto
{
Name = "Sylas",
Bio = "Bad",
Class = ChampionClassDto.Tank,
Icon = "",
Image = new LargeImageDto() { Base64 = "" },
Skins = new List<SkinDto>()
};
//Act
await champs.Post(ChampionDto);
var championsResult = await champs.Put(ChampionDto.Name, ChampionDtoPut);
//Assert
var objectResult = championsResult as OkObjectResult;
Assert.IsNotNull(objectResult);
var champions = objectResult?.Value as ChampionDto;
Assert.IsNotNull(champions);
Assert.AreNotEqual(ChampionDto.Bio, champions.Bio);
Assert.AreEqual(ChampionDtoPut.Bio, champions.Bio);
}
[TestMethod]
public async Task TestDeleteChampion()
{
//Arange
//Act
var total = await stub.ChampionsMgr.GetNbItems();
var championsResult = await champs.Delete("Akali");
//Assert
var objectResult = championsResult as OkObjectResult;
Assert.IsNotNull(objectResult);
Assert.AreEqual(objectResult.Value, true);
Assert.AreNotEqual(await stub.ChampionsMgr.GetNbItems(), total);
}
}
}
Loading…
Cancel
Save