Oussama SAIDI

0 %
Oussama SAIDI
Consultant .Net
Sharepoint Office 365

  • Résidence:
    France
  • Ville:
    Lille
Arabe
Français
Anglais
.Net
Html/Css/Js
Web Api
Base de données
  • C#,.Net Core, .Net MVC
  • Rest Api
  • Docker
  • GIT,TFS

Premiers pas avec AutoMapper dans ASP.NET Core

octobre 3, 2022

Dans cet article, nous allons apprendre à utiliser AutoMapper dans une application ASP.NET Core .

Nous allons commencer par examiner ce qu’est AutoMapper et quel problème il résout. Ensuite, nous allons expliquer comment nous pouvons utiliser AutoMapper dans notre application MVC. Après cela, nous en apprendrons davantage sur les directives d’utilisation et les meilleures pratiques. Nous examinerons également ce qui se passe dans les coulisses et comment aplatir des modèles d’objets complexes.

Table des matières

Qu’est-ce qu’AutoMapper ?

Tout d’abord AutoMapper est une bibliothèque simple qui nous aide à transformer un type d’objet en un autre. Il s’agit d’un mappeur d’objet à objet basé sur des conventions qui nécessite très peu de configuration. 

Le mappage objet à objet fonctionne en transformant un objet d’entrée d’un type en un objet de sortie d’un type différent.

Un cas d’utilisation d’AutoMapper

AutoMapper a été conçu pour résoudre un problème complexe auquel la plupart des développeurs sont confrontés dans leur vie quotidienne : écrire du code qui mappe un type d’objet à un autre. Ce type de code est plutôt fastidieux et ennuyeux à écrire, alors pourquoi ne pas laisser ce travail à ce petit outil ?

Ce qui rend AutoMapper intéressant, c’est qu’il fournit des conventions faciles à utiliser pour simplifier la tâche consistant à déterminer comment mapper Type A vers Type B. Tant qu’il Type B suit les conventions établies d’AutoMapper, presque aucune configuration n’est nécessaire pour mapper deux types.

Voici un scénario courant. Nous avons créé une application et nous souhaitons conserver la séparation entre nos modèles de domaine et nos modèles de vue. 

Pour ce faire, nous devons écrire le code pour adapter notre modèle de domaine à notre modèle de vue. Ensuite, à mesure que nous ajoutons plus de vues et de modèles de domaine, nous finissons par écrire plus d’adaptateurs. Plus tard, nous devrons écrire encore plus d’adaptateurs pour mapper nos objets de transfert de données de la couche de base de données dans nos objets de domaine. 

C’est banal et répétitif. Et c’est là AutoMapper qu’intervient.

Comment utiliser AutoMapper dans notre application

Voyons comment ajouter Automapper dans notre application .NET Core .

Installation d’AutoMapper

La première étape consiste à installer le package NuGet correspondant :

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

Si nous installons le AutoMapper.Extensions.Microsoft.DependencyInjection package , il installera automatiquement le package AutoMapper pour nous puisqu’il y fait référence.

Configuration d’AutoMapper

Nous expliquerons la configuration pour les versions .NET 5 et .NET 6 et supérieures.

Après avoir installé le package requis, l’étape suivante consiste à configurer les services. Faisons-le en Startup.cs classe :

public void ConfigureServices(IServiceCollection services)
{
    services.AddAutoMapper(typeof(Startup));
    services.AddControllersWithViews();
}

Pour .NET 6, nous devons modifier la classe Program :

builder.Services.AddAutoMapper(typeof(Program)); 
builder.Services.AddControllersWithViews();

C’est ça. AutoMapper est installé et configuré dans notre projet. Voyons maintenant comment l’utiliser avec nos objets.

Usage

Disons que nous avons un objet domaine nommé User:

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
}

Dans la couche UI, nous aurions un ViewModel pour afficher les informations utilisateur :

public class UserViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

Voyons maintenant comment nous allons convertir notre objet de domaine en un modèle de vue.

Profils

Une bonne façon d’organiser nos configurations de mappage est avec Profiles. Nous devons créer des classes qui héritent de Profile class et mettre la configuration dans le constructeur :

public UserProfile()
{
    CreateMap<User, UserViewModel>();
}

UserProfile La classe crée le mappage entre notre Userobjet de domaine et UserViewModel. Dès que notre application démarre et initialise AutoMapper, AutoMapper analysera notre application et recherchera les classes qui héritent de la Profile classe et chargera leurs configurations de mappage.

Maintenant, définissons un contrôleur et utilisons les fonctionnalités de mappage automatique que nous venons d’ajouter :

public class UserController : Controller
{
    private readonly IMapper _mapper;

    public UserController(IMapper mapper)
    {
        _mapper = mapper;
    }

    public IActionResult Index()
    {
        // Populate the user details from DB
        var user = GetUserDetails();

        UserViewModel userViewModel = _mapper.Map<UserViewModel>(user);

        return View(userViewModel);
    }
}

Tout d’abord, nous injectons l’ mapper objet dans le contrôleur. Ensuite, nous appelons la Map()méthode, qui mappe l’ User objet à l’ UserViewModel objet. De plus, faites attention à une méthode locale GetUserDetails que nous utilisons pour le stockage local des données. Vous pouvez trouver son implémentation dans notre code source.

Créons une méthode View pour l’ Index action comme expliqué dans la section de l’article : Création de vues .

Exécutons maintenant l’application :

AutoMapper dans ASP.NET Core

Nous pouvons voir que notre User objet de domaine est correctement mappé à l’ UserViewModel objet.

Mappage vers des propriétés avec des noms différents

Eh bien, c’était assez simple, n’est-ce pas ? 

Mais que se passe-t-il si nous avons des noms de propriété différents dans nos objets source et destination. Voyons comment faire le mappage dans ces cas.

Modifions les noms de propriété dans UserViewModel la classe :

public class UserViewModel
{
    public string FName { get; set; }
    public string LName { get; set; }
    public string Email { get; set; }
}

Ici, nous devons mapper les propriétés de l’ User objet domaine à notre UserViewModel:

User.FirstName -> UserViewModel.FName
User.LastName -> UserViewModel.LName
User.EMail -> UserViewModel.Email

Modifions donc le mappage dans la UserProfile classe :

public UserProfile()
{
    CreateMap<User, UserViewModel>()
        .ForMember(dest =>
            dest.FName,
            opt => opt.MapFrom(src => src.FirstName))
        .ForMember(dest =>
            dest.LName,
            opt => opt.MapFrom(src => src.LastName))
}

Nous utilisons la CreateMap()méthode pour créer un mappage en fournissant les propriétés source et destination. 

Si nous voulons personnaliser la configuration pour des membres individuels, nous pouvons utiliser la ForMember()méthode qui a les paramètres destinationMember, qui est de type Expression et memberOptions, qui est de type Action .

Par exemple, le code ci-dessus mappe FirstName et LastNameles propriétés de l’ Userobjet à la FName et à la LName propriété de UserViewModel respectivement.

Après avoir apporté ces modifications, exécutons à nouveau l’application. Nous pouvons voir que ces propriétés sont correctement mappées.

Cartographie inversée

Jusqu’à présent, nous n’avons examiné que le mappage unidirectionnel, ce qui signifie que si nous avons deux types Type A et Type B, nous mappons uniquement Type A vers Type B. Mais, en utilisant la capacité de mappage inversé d’Automapper, il est possible d’obtenir un mappage bidirectionnel :

public UserProfile()
{
    CreateMap<User, UserViewModel>()
        .ForMember(dest =>
            dest.FName,
            opt => opt.MapFrom(src => src.FirstName))
        .ForMember(dest =>
            dest.LName,
            opt => opt.MapFrom(src => src.LastName))
        .ReverseMap();
}

Une fois le Reverse Mapping configuré, nous pouvons remonter de la destination au type de source :

var mappedUser = _mapper.Map<User>(userViewModel);

De cette façon, nous pouvons facilement réaliser un mappage bidirectionnel entre les types à l’aide des capacités de mappage inversé d’AutoMapper. 

Juste une note. Nous pouvons également utiliser AutoMapper de la même manière dans le projet d’API Web ASP.NET Core , l’implémentation est la même, nous ne mapperons pas les modèles de vue mais, par exemple, nos classes DTO.

Dans les coulisses d’AutoMapper

Nous avons vu la magie d’AutoMapper en action. Alors que se passe-t-il en arrière-plan ? 

AutoMapper utilise un concept de programmation appelé Reflection pour récupérer les métadonnées de type des objets. Nous pouvons utiliser la réflexion pour obtenir dynamiquement le type d’un objet existant et invoquer ses méthodes ou accéder à ses champs et propriétés. 

Ensuite, en fonction des conventions et des configurations définies, nous pouvons facilement mapper les propriétés des deux types. AutoMapper a été construit autour de ce concept.

Consignes d’utilisation et bonnes pratiques d’AutoMapper

Comme pour tous les autres composants que nous utilisons dans notre application, il existe certaines directives d’utilisation et les meilleures pratiques que nous devons suivre lors de l’utilisation d’AutoMapper.

À faire 

  • Utilisez toujours le AutoMapper.Extensions.Microsoft.DependencyInjection package dans ASP.NET Core avec services.AddAutoMapper(assembly[]). Ce package effectuera toute l’analyse et l’ enregistrement de l’injection de dépendances . Nous avons seulement besoin de déclarer les configurations de profil.
  • Organisez toujours la configuration en Profiles. Profiles permettent de regrouper une configuration commune et d’organiser les mappings par usage. Cela nous permet de rapprocher la configuration de mappage de l’endroit où elle est utilisée, au lieu d’un seul fichier de configuration qui devient difficile à modifier/maintenir.
  • Utilisez toujours les options de configuration prises en charge par LINQ plutôt que leurs homologues, car les extensions de requête LINQ offrent les meilleures performances de toutes les stratégies de mappage.
  • Toujours aplatir les DTO. AutoMapper peut gérer les propriétés de mappage ABC dans ABC. En aplatissant notre modèle, nous créons un objet plus simplifié qui ne nécessitera pas beaucoup de navigation pour accéder aux données.
  • Mettez toujours des propriétés calculées simples communes dans le modèle source. De même, nous devons placer les propriétés calculées spécifiques au modèle de destination dans le modèle de destination.

A ne pas faire

  • N’appelez pas CreateMap()à chaque demande. Il n’est pas recommandé de créer la configuration pour chaque demande de mappage. La configuration du mappage doit être effectuée une fois au démarrage.
  • N’utilisez pas de cartes en ligne. Les cartes en ligne peuvent sembler plus faciles pour des scénarios très simples, mais nous perdons la facilité de configuration.
  • Si nous devons écrire un comportement de mappage complexe, il serait peut-être préférable d’éviter d’utiliser AutoMapper pour ce scénario.
  • Ne placez aucune logique qui ne corresponde pas strictement au comportement de mappage dans la configuration. AutoMapper ne doit pas exécuter de logique métier, il ne doit gérer que le mappage.
  • Évitez de partager des DTO sur plusieurs cartes. Modélisez vos DTO autour d’actions individuelles, et si vous devez le modifier, vous n’affectez que cette action.
  • Ne créez pas de DTO avec des associations circulaires. AutoMapper le prend en charge, mais cela prête à confusion et peut entraîner de très mauvaises performances. Au lieu de cela, nous pouvons créer des DTO distincts pour chaque niveau de la hiérarchie que nous voulons.

Aplatir des modèles d’objets complexes dans AutoMapper

AutoMapper prend en charge l’aplatissement des modèles d’objets complexes en DTO ou un autre modèle d’objet simple. Par exemple, les objets de domaine  ont généralement un modèle d’objet complexe avec de nombreuses associations entre eux, mais les ViewModels ont généralement un modèle d’objet plat. 

Nous pouvons mapper des objets de domaine sur des ViewModels avec Flattening d’ AutoMapper

Si nous suivons les conventions de dénomination appropriées pour nos modèles d’objets, il n’est pas nécessaire de fournir de code de configuration supplémentaire. AutoMapper fonctionne avec des conventions et mappe notre modèle d’objet du complexe au plat/simple.

AutoMapper utilise les conventions suivantes :

  • Il mappera automatiquement les propriétés avec les mêmes noms.
  • Si l’objet source est associé à d’autres objets, il essaiera de mapper avec des propriétés sur l’objet de destination dont le nom est une combinaison du nom de la classe source et du nom de la propriété dans le cas Pascal
  • Il essaiera de mapper des méthodes sur l’objet source qui a un Get préfixe avec une propriété sur l’objet de destination avec le nom excluant le Get préfixe.

Si nous suivons ces conventions, AutoMapper mappera automatiquement nos objets. Sinon, nous devrons configurer à l’ AutoMapper aide de l’ API Fluent .

Modifions notre Userobjet en ajoutant un objet enfant Address:

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public Address Address { get; set; }

    public string GetFullName()
    {
        return $"{this.LastName}, {this.FirstName}";
    }
}

Et voici à quoi Address ressemble la classe :

public class Address
{
    public int Id { get; set; }
    public string Door { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
    public string ZipCode { get; set; }
}

Notez également que nous avons ajouté une méthode GetFullName()pour obtenir le nom complet de l’utilisateur.

Modifions la UserViewModel classe :

public class UserViewModel
{
    [Display(Name = "Full Name")]
    public string FullName { get; set; }
    [Display(Name = "Country")]
    public string AddressCountry { get; set; }
    public string Email { get; set; }
}

Maintenant, modifions la classe de profil pour utiliser les conventions par défaut :

public UserProfile()
{
    CreateMap<User, UserViewModel>();
}

Exécutons à nouveau l’application :

AutoMapper dans ASP.NET Core

Cette fois, nous pouvons voir que la GetFullName()méthode sur l’objet source est correctement mappée à la FullName propriété sur l’objet de destination.

De même, la propriété User.Address.Country est automatiquement mappée sur UserViewModel.AddressCountry

Ces mappages sont correctement gérés par l’ à l’ AutoMapper aide de ses conventions par défaut.

Conclusion

Dans cet article, nous avons appris les concepts suivants :

  • Le composant AutoMapper – qu’est-ce que c’est et quand l’utiliser ?
  • Installation, configuration et utilisation du composant AutoMapper dans notre application ASP.NET Core
  • Comment AutoMapper fonctionne dans les coulisses
  • Consignes d’utilisation et meilleures pratiques lors de l’utilisation d’AutoMapper.
  • Aplatir un modèle d’objet complexe à l’aide des conventions par défaut d’AutoMapper.

C’est tout pour le moment. J’espère que vous avez apprécié l’article. Nous aborderons des sujets plus avancés liés à AutoMapper dans l’un des articles suivants .

Derniers Articles

Publié dans .Net Core, Asp .Net, automapper, C Sharp, c#Tags:
© 2022 Tous les droits sont réservés.
oussamasaidi.com