Aller au contenu principal

24-2 Le retour des DTO

On expose que très rarement le contenu entier d'une entité provenant de la base de données.

En effet, le retour d'un API est "publiquement" accessible. En utilisant les outils développeur du navigateur, on peut inspecter les requêtes réseau et obtenir le résultat de l'API.

Et s'il y avait un champ qu'on ne veut pas exposer via l'API? Le cas évident est le hash de mot de passe d'un utilisateur, par exemple, ou autres informations sensibles.

Et même si ce n'est pas le cas dans l'immédiat, un développeur peut ajouter une colonne "sensible" à un modèle et puisque le modèle est retourné directement de l'API, automatiquement cette nouvelle donnée sensible se retrouvera être retournée.

Pour pallier à cette situation, nous avons vu en Web 3 le concept de DTO (Data Transfer Object). Ils sont utilisés pour échanger de l'information entre un client (Blazor dans le navigateur par exemple) et un serveur (l'API).

DTO

Les DTO sont essentiellement des conteneurs de données et n'ont généralement pas de logique ou de comportement.

Ils sont des objets simples utilisés pour transférer des données entre différentes couches d'une application. Ils favorisent la séparation des responsabilités et la modularité.

Créer le DTO EvenementDto

Plutôt que de retourner une liste d'événements via l'API, on retournera une liste de EvenementDto. C'est un peu l'équivalent du ViewModel, mais appliqué à l'API.

Les DTO appartiennent à la couche Application puisqu'ils sont partis des particularités de notre implémentation logicielle.

  1. Sous le projet Snowfall.Application -> Clic droit -> Add -> Directory
  2. Nommez le dossier Dtos
  3. Sous le dossier Dtos -> Clic droit -> Add -> Directory
  4. Nommez le dossier Evenements
  5. Sous le dossier Dtos/Evenements -> Clic droit -> Add -> Class/Interface
  6. Nommez la classe EvenementDto
  7. Mettez-y une implémentation de base qui correspond à la définition d'un événement:
    Snowfall.Application/Dtos/Evenements/EvenementDto.cs
    public class EvenementDto
    {
    public int Id { get; set; }
    public string Nom { get; set; }
    public string? Description { get; set; }
    public string? ImagePath { get; set; }
    public DateTime Date { get; set; }
    public Decimal Prix { get; set; }
    public int Capacite { get; set; }
    public int VilleId { get; set; }
    }

Retourner un DTO

Comment est-ce qu'on retourne une liste de EvenementDto plutôt qu'une liste de Evenement, alors que le service retourne des Evenement?

Peut-être pourrait-on caster la liste en une liste de type EvenementDto?

Snowfall.Web.Api/Controllers/EvenementsController.cs
public async Task<IActionResult> Index()
{
List<Evenement> evenements = await _evenementService.GetAll();

// ??
return Ok((List<EvenementDto>)evenements);
}

Le compilateur n'aime pas vraiment cette approche et nous informe qu'il est impossible d'effectuer cette opération.

Pourquoi pas itérer au travers de la liste d'Evenement et pour chacun, créer un EvenementDto correspondant pour finalement l'ajouter à une liste de EvenementDto?

Quelque chose comme ceci:

Snowfall.Web.Api/Controllers/EvenementsController.cs
public async Task<IActionResult> Index()
{
List<Evenement> evenements = await _evenementService.GetAll();

List<EvenementDto> evenementDtos = new List<EvenementDto>();
foreach (var evenement in evenements)
{
evenementDtos.Add(new EvenementDto
{
Id = evenement.Id,
Capacite = evenement.Capacite,
Date = evenement.Date,
Description = evenement.Description,
ImagePath = evenement.ImagePath,
Nom = evenement.Nom,
Prix = evenement.Prix,
VilleId = evenement.VilleId
});
}

return Ok(evenementDtos);
}

Test

Essayez via Scalar ou Postman, le tout fonctionne, mais ce n'est pas particulièrement élégant et c'est très fastidieux!